Interview & Career • 10 min read • 09/10/2026

The Roadmap from Middle to Senior Engineer: A Checklist of Skills and Systems Thinking

Bài này có bản tiếng Việt. Đọc bản tiếng Việt →

Nguyen Hai Trinh

Nguyen Hai Trinh • Senior Software Engineer @ SmileViet

A staircase leading upward
Photo: Carole Raddato from Frankfurt, Germany · CC BY-SA 2.0

“My code is solid, I ship every feature on time. So what am I missing to become a Senior?” I get this question a lot from Middle Engineers.

The short answer: shipping on time is necessary, but it isn’t sufficient. The gap is somewhere else. It’s in how you look at a problem before you touch the keyboard.

The four axes below are what I grade myself on every time I change companies, which for me meant Bolt Technologies, then Cognisian, then SmileViet.

Where Middle and Senior actually differ

A strong Middle Engineer will:

  • Pick up a ticket, understand the requirements, implement it correctly, and write thorough tests.
  • Use the patterns the team has already agreed on.
  • Debug a complex bug, given enough time.

A strong Senior Engineer does a few more things that Middles usually don’t:

  • Asks questions back before coding: “Does this requirement really need strong consistency, or is eventual consistency enough?” That one question leads to completely different architectures.
  • Anticipates operating costs. “It works” isn’t enough. It has to work at 10x the scale, and you should know who gets woken up at 3 a.m. when it breaks.
  • Raises risks proactively: tells the PM/stakeholders about trade-offs early, instead of quietly picking whichever solution is safest for yourself.

Put briefly, a Middle optimizes for “getting it done”, and a Senior optimizes for “the right thing, at the right time, at the right cost”.

Four axes to grade yourself on

Nobody has all four from day one. These are the four questions I come back to regularly:

flowchart TD
    ROOT["Four self-grading axes"] --> T1["Axis 1 - Technical Depth"]
    ROOT --> T2["Axis 2 - System Thinking"]
    ROOT --> T3["Axis 3 - Ownership & Communication"]
    ROOT --> T4["Axis 4 - Mentorship"]
    T1 --> T1a["Explain the layer underneath<br/>what queries the ORM generates, connection pool, event loop"]
    T1 --> T1b["When the system is slow, where do you measure first<br/>database, network, CPU or GC"]
    T2 --> T2a["Failure modes<br/>if service B dies midway, does A get stuck"]
    T2 --> T2b["Blast radius<br/>if a deploy goes wrong, how many services and customers are hit"]
    T3 --> T3a["Write a short design doc before coding"]
    T3 --> T3b["Incidents: step up and coordinate instead of waiting for direction"]
    T4 --> T4a["Review code to explain why, not just to catch bugs"]
    T4 --> T4b["Document architecture decisions for whoever comes next"]

Axis 1: Technical Depth

It isn’t about knowing lots of frameworks. It’s about understanding why a framework behaves the way it does.

  • Can you explain what happens a layer below the tools you use every day? For example: what queries the ORM generates, how the connection pool behaves when it runs out of connections, how the event loop handles I/O.
  • When the system is slow, do you know where to start measuring (database, network, CPU, or GC) instead of guessing and changing things at random?
  • Have you ever read the source code of an important library your team depends on, rather than just the docs?

At Bolt Technologies, I once optimized an account-loading API that took 5+ seconds. A Middle Engineer would immediately think “add a cache”. Before caching, I measured and found the query was doing N+1 on a table without the right index. I fixed the index first, then added a Caffeine cache at the application layer to cut the load further, and latency came down to about 0.2 seconds. If I had only cached without fixing the root cause, a cache miss would have been just as slow as before, and the bug would have come back in another form.

Axis 2: System Thinking

This is the hardest axis to train on your own, because it takes hands-on experience with large systems.

  • When you design a feature, do you think about failure modes? If service B dies midway, does service A get stuck forever?
  • Can you tell when to go synchronous and when to use a queue to decouple two systems?
  • Can you assess the blast radius of a change? If a deploy goes wrong, how many services and customers are affected?

At Cognisian, I built a healthcare data analytics dashboard connected to a StarRocks OLAP database. The hard part wasn’t “making the query faster”. It was understanding that the query runs on a fact table with hundreds of millions of rows, and without the right partitioning and pre-aggregation, no amount of caching would save it. The drop from 1.5 seconds to about 250ms came from redesigning the data model, not from tuning application-layer code.

Axis 3: Ownership & Communication

Becoming a Senior doesn’t mean you get better at working alone. It means the whole team works better because of how clear you are.

  • Do you proactively write a short design doc before starting a complex feature, so others can review it before it’s too late?
  • When an incident happens, do you step up and take responsibility for coordinating, instead of waiting for someone else to give direction?
  • Can you say “no” or “not now” to an unreasonable request, with a clear reason, instead of quietly working overtime to absorb it?

When I moved to SmileViet to build the backend for an e-commerce platform combined with travel (a retail + travel marketplace), one of the first things I did wasn’t coding. I read through the entire existing booking flow, noted the ambiguous spots, and talked with the team before proposing any changes. The reason is simple: on a platform with a booking flow (tours, tickets, visas) already running in production, one wrong line of idempotency logic can cause a real double-booking for a real customer.

Axis 4: Mentorship

This is the axis people skip most often, yet companies value it highly because it multiplies the capability of the whole team.

  • When you review code, do you spend time explaining why it should be changed, not only catching bugs?
  • Do you document important architecture decisions so the next person doesn’t have to ask from scratch?
  • Are you willing to let someone pair-program with you, even when it’s slower than doing it alone?

The roadmap isn’t a straight line

Nobody hits all four axes at once from day one. It took me about 2-3 years of rotating through companies in completely different domains. Each time I changed domain, one of the four axes got partly “reset”, because the old domain knowledge didn’t transfer directly.

Here are those three stretches, with the examples I keep retelling:

timeline
    title 2-3 years, three domains
    Bolt Technologies : derivatives trading : account-loading API slow at 5+ seconds, fixed N+1 and the index, then added a Caffeine cache, down to about 0.2 seconds
    Cognisian : AI healthcare : StarRocks OLAP dashboard, redesigned partitioning and pre-aggregation, 1.5 seconds down to about 250ms
    SmileViet : travel marketplace : read the booking flow carefully before proposing changes, avoiding double-booking

What stayed constant through every move was systems thinking and the habit of asking the right questions before coding. Everything else (framework names, database names, domain names) changed.

If you’re at the Middle stage and wondering what you’re missing, try grading yourself honestly on the four axes above. The answer usually isn’t learning one more new framework. It’s in how you ask questions before you start solving the problem.

Need a developer for a contract or freelance project?

I take on fullstack projects — Go backends, React/Next.js frontends, or both ends. Send a few lines about the scope and timeline and I'll reply within 48 hours.