Lộ Trình Từ Middle Lên Senior Engineer: Checklist Kỹ Năng Và Tư Duy Hệ Thống
Bài này có bản tiếng Anh. Read in English →
Nguyen Hai Trinh • Senior Software Engineer @ SmileViet
“Em code ổn, feature nào cũng làm xong đúng hạn, vậy còn thiếu gì để lên Senior?” Câu này mình nhận được rất nhiều từ các bạn Middle Engineer.
Trả lời ngắn: code xong đúng hạn là điều kiện cần, không phải điều kiện đủ. Khoảng cách nằm chỗ khác. Ở cách bạn nhìn một vấn đề trước khi chạm vào bàn phím.
Bốn trục dưới đây là thứ mình tự chấm mỗi lần chuyển công ty, qua Bolt Technologies, Cognisian, rồi SmileViet.
Middle và Senior khác nhau ở đâu
Một Middle Engineer giỏi sẽ:
- Nhận ticket, hiểu yêu cầu, implement đúng, viết test đầy đủ.
- Biết dùng đúng pattern đã được team thống nhất từ trước.
- Debug được bug phức tạp khi có đủ thời gian.
Một Senior Engineer giỏi làm thêm mấy việc Middle thường không làm:
- Đặt câu hỏi ngược lại trước khi code: “Yêu cầu này có thật sự cần consistency mạnh không, hay eventual consistency là đủ?” Câu hỏi này quyết định kiến trúc hoàn toàn khác nhau.
- Lường trước chi phí vận hành: “chạy được” chưa đủ, phải chạy được ở quy mô gấp 10 lần, và biết khi nó hỏng thì ai là người bị đánh thức lúc 3h sáng.
- Chủ động giao tiếp rủi ro: báo sớm cho PM/stakeholder về trade-off, thay vì âm thầm chọn giải pháp an toàn nhất cho bản thân.
Nói gọn: Middle tối ưu cho “xong việc”, Senior tối ưu cho “đúng việc, đúng thời điểm, đúng chi phí”.
Bốn trục để tự chấm
Không ai đủ cả bốn trục ngay từ ngày đầu. Đây là bốn câu hỏi mình quay lại định kỳ:
flowchart TD
ROOT["Bốn trục tự chấm"] --> T1["Trục 1 - Technical Depth"]
ROOT --> T2["Trục 2 - System Thinking"]
ROOT --> T3["Trục 3 - Ownership & Communication"]
ROOT --> T4["Trục 4 - Mentorship"]
T1 --> T1a["Giải thích được tầng dưới<br/>ORM sinh query gì, connection pool, event loop"]
T1 --> T1b["Hệ thống chậm thì đo ở đâu trước<br/>database, network, CPU hay GC"]
T2 --> T2a["Failure mode<br/>service B chết giữa chừng thì A có kẹt không"]
T2 --> T2b["Blast radius<br/>deploy sai thì bao nhiêu service, khách hàng dính"]
T3 --> T3a["Viết design doc ngắn trước khi code"]
T3 --> T3b["Sự cố: đứng ra điều phối thay vì chờ chỉ đạo"]
T4 --> T4a["Review code để giải thích tại sao, không dừng ở bắt lỗi"]
T4 --> T4b["Tài liệu hoá quyết định kiến trúc cho người sau"]
Trục 1: Technical Depth
Không phải biết nhiều framework, mà là hiểu tại sao framework đó hoạt động như vậy.
- Bạn có thể giải thích được điều gì xảy ra ở tầng dưới của công cụ mình dùng hàng ngày không? Ví dụ: ORM sinh ra query gì, connection pool hoạt động ra sao khi hết kết nối, event loop xử lý I/O như thế nào.
- Khi hệ thống chậm, bạn có biết bắt đầu đo ở đâu trước (database, network, CPU, hay GC) thay vì đoán mò và sửa ngẫu nhiên?
- Bạn có từng đọc source code của một thư viện quan trọng mà team đang phụ thuộc vào, thay vì chỉ đọc docs?
Khi còn ở Bolt Technologies, mình từng tối ưu một API load tài khoản bị chậm 5 giây+. Một Middle Engineer sẽ nghĩ ngay đến “thêm cache”. Nhưng trước khi cache, mình đo được là query đang N+1 trên một bảng không có index đúng chỗ — fix index trước, sau đó mới thêm Caffeine cache ở tầng application để giảm tải thêm, kết quả giảm latency xuống còn ~0.2 giây. Nếu chỉ cache mà không fix gốc rễ, cache miss vẫn sẽ chậm y như cũ, và bug sẽ quay lại dưới một hình hài khác.
Trục 2: System Thinking
Đây là trục khó nhất để tự luyện vì nó đòi hỏi kinh nghiệm thực chiến với hệ thống lớn.
- Khi thiết kế một tính năng, bạn có nghĩ đến failure mode không? Nếu service B chết giữa chừng, service A có bị kẹt mãi mãi không?
- Bạn có phân biệt được khi nào nên dùng đồng bộ, khi nào nên dùng hàng đợi (queue) để tách rời (decouple) hai hệ thống?
- Bạn có đánh giá được blast radius của một thay đổi — nếu deploy sai, có bao nhiêu service/khách hàng bị ảnh hưởng?
Ở Cognisian, khi làm dashboard phân tích dữ liệu y tế kết nối StarRocks OLAP, phần khó không nằm ở “query nhanh hơn”. Nằm ở chỗ phải hiểu rõ: query này chạy trên bảng fact hàng trăm triệu dòng, nếu không thiết kế đúng partition và pre-aggregation thì thêm bao nhiêu cache cũng không cứu được. Khoản giảm từ 1.5 giây xuống ~250ms đến từ việc thiết kế lại mô hình dữ liệu, không phải tối ưu code ở tầng ứng dụng.
Trục 3: Ownership & Communication
Lên Senior không có nghĩa là làm việc một mình giỏi hơn. Nghĩa là cả team làm việc hiệu quả hơn nhờ sự rõ ràng của bạn.
- Bạn có chủ động viết design doc ngắn trước khi bắt tay vào một tính năng phức tạp, để người khác review trước khi quá muộn?
- Khi có sự cố, bạn có đứng ra nhận trách nhiệm điều phối thay vì chờ người khác chỉ đạo?
- Bạn có khả năng nói “không” hoặc “chưa nên làm bây giờ” với một yêu cầu không hợp lý, kèm lý do rõ ràng, thay vì âm thầm làm overtime để gồng?
Khi chuyển sang SmileViet làm backend cho nền tảng thương mại điện tử kết hợp du lịch (retail + travel marketplace), một trong những việc đầu tiên mình làm không phải là code. Mình đọc kỹ toàn bộ luồng booking hiện tại, note lại những điểm mơ hồ, rồi trao đổi với team trước khi đề xuất thay đổi. Lý do đơn giản: nền tảng có luồng đặt chỗ (tour, vé, visa) đã chạy production thì sai một dòng logic idempotency có thể gây double-booking thật cho khách hàng thật.
Trục 4: Mentorship
Đây là trục nhiều người bỏ qua nhất, nhưng công ty đánh giá rất cao vì nó nhân bản năng lực của cả team.
- Bạn có dành thời gian review code không chỉ để bắt lỗi, mà để giải thích tại sao nên sửa theo cách khác?
- Bạn có tài liệu hoá lại những quyết định kiến trúc quan trọng để người sau không phải hỏi lại từ đầu?
- Bạn có sẵn sàng để người khác pair-program cùng, kể cả khi điều đó chậm hơn so với tự làm một mình?
Lộ trình không phải đường thẳng
Không ai đạt đủ 4 trục cùng lúc ngay từ ngày đầu. Mình mất khoảng 2-3 năm xoay vòng giữa các công ty với domain hoàn toàn khác nhau. Mỗi lần đổi domain, một trong 4 trục lại bị “reset” một phần, vì kiến thức domain cũ không áp dụng trực tiếp được.
Ba chặng đó, kèm ví dụ mình vẫn hay kể lại:
timeline
title 2-3 năm, ba domain
Bolt Technologies : derivatives trading : API load tài khoản chậm 5 giây+, fix N+1 và index rồi thêm Caffeine cache, còn ~0.2 giây
Cognisian : AI healthcare : dashboard StarRocks OLAP, thiết kế lại partition và pre-aggregation, 1.5 giây xuống ~250ms
SmileViet : travel marketplace : đọc kỹ luồng booking trước khi đề xuất thay đổi, tránh double-booking
Thứ giữ nguyên qua mọi lần chuyển đổi là tư duy hệ thống và thói quen đặt câu hỏi đúng trước khi code. Phần còn lại — tên framework, tên database, tên domain — đổi hết.
Nếu đang ở giai đoạn Middle và tự hỏi mình còn thiếu gì, thử tự chấm theo 4 trục trên một cách thành thật. Câu trả lời thường không nằm ở việc học thêm một framework mới. Nằm ở cách đặt câu hỏi trước khi bắt tay vào giải quyết vấn đề.
Đọc tiếp
- Phỏng Vấn Tech Lead: Vòng Leadership, Quyết Định Kỹ Thuật Và MentoringPhỏng Vấn & Sự Nghiệp
- Bí kíp phỏng vấn Senior Fullstack: Go Concurrency, System Design & Behavior STARPhỏng Vấn & Sự Nghiệp
- Phỏng Vấn Frontend Lead: Frontend System Design Với Micro-Frontend, Monorepo Và Trade-offPhỏng Vấn & Sự Nghiệp
Cần người cho dự án contract hoặc freelance?
Mình nhận dự án fullstack — backend Go, frontend React/Next.js, hoặc cả hai đầu. Gửi vài dòng về phạm vi công việc và thời gian, mình phản hồi trong 48 giờ.