Nauman's Blog
Career

From Mid Level to Senior Engineer: What Actually Changes

The senior title isn't about harder code. What changed for me: ownership, ambiguity, communication, and multiplying the effect of everyone around me.

By Nauman Moazzam 10 min read

For about two years I thought I knew how to become a senior software engineer: write harder code. Take the gnarliest tickets, learn the deepest parts of the stack, be more technical than everyone in the room. Then I made the mid level to senior engineer transition myself, and the promotion was not a bigger version of the job I already had. It was a different job that shared a codebase with my old one.

Nobody said that out loud beforehand. Career ladder documents describe the change with abstract nouns like “scope,” “impact,” and “influence,” which read as filler until you’ve lived them. So this is the version I wish I’d read as a mid level engineer: what actually changed, where I struggled, and what you can practice right now without waiting for permission.

The mid level shift nobody explains

As a mid level engineer, my unit of work was the task. Someone (a lead, a product manager, a ticket) handed me a reasonably well defined problem, and I solved it well. I was fast, my PRs were clean, and I felt productive because the loop was tight: pick up ticket, ship ticket, repeat.

The senior shift is that your unit of work becomes the outcome, and outcomes don’t fit in tickets. The question stops being “did I finish the task?” and becomes “did the thing the task was supposed to achieve actually happen?” Those are shockingly different questions.

Mid level me would implement a caching layer exactly as specified, ship it, and move on. Senior me is on the hook when the cache invalidation bug surfaces three weeks later, when the metrics show it didn’t actually reduce p95 latency, and when the on call engineer can’t debug it at 2 a.m. Nobody assigned me those follow ups. Owning the outcome means the work isn’t done until the problem is solved, and stays solved.

That reframing changes everything downstream. You start asking “what’s the actual problem?” before writing code. You get serious about observability because you’ll be the one staring at dashboards later. You write the runbook nobody asked for. None of it shows up in a velocity chart, and all of it is the job.

The uncomfortable part: for a while, this made me feel slower. My ticket throughput dropped. It took months to accept that this was the point: I was trading visible busyness for durable results.

Ambiguity is the actual job

The clearest signal that I’d crossed the line wasn’t a title change. It was the day my manager stopped handing me tasks and started handing me sentences. “Customers are complaining that exports are slow.” “We should probably do something about our test flakiness.” That’s the whole assignment.

Mid level me would have panicked or, worse, guessed at an interpretation and started coding. Senior work is turning that vague sentence into a shippable plan, and there’s a repeatable pattern I now run almost on autopilot:

  1. Find the real complaint. “Exports are slow”: slow for whom? Which exports? Since when? Half the time the actual problem is narrower and stranger than the sentence suggests. Twenty minutes of reading support threads and querying logs routinely saves twenty days of building the wrong thing.
  2. Define what “fixed” means before touching code. A measurable target, “95% of exports under 30 seconds,” turns an endless project into a finite one. Without it you’re doing vibes driven optimization with no way to declare victory.
  3. Write down two or three approaches, including the boring one. There’s almost always a small, unglamorous fix that gets 80% of the value. Listing it next to the ambitious rewrite forces an honest conversation about cost.
  4. Cut scope publicly. Say what you’re not doing, in writing, where stakeholders can object. “This won’t fix scheduled exports; that’s a separate problem” prevents a month of misaligned expectations.
  5. Ship something inside two weeks. Not the whole plan, a slice that proves the approach and produces feedback. Long running dark work is where senior projects go to die.

None of these steps is hard. The hard part is holding your nerve in the fog, because ambiguity is uncomfortable and code is comforting. I still feel the pull to just start typing. I’ve just learned to treat it as a warning sign.

Your code matters less than you think

This is the one I resisted longest. Code quality still matters. What stopped mattering was code as the primary way I create value, because past a certain level, the expensive failures in software aren’t bad functions. They’re good functions solving the wrong problem, or right decisions that nobody understood, remembered, or agreed to.

The highest leverage artifact I produce now is usually a document, not a diff. A one page design doc that gets torn apart in review costs a day and saves a quarter. I had to unlearn how I wrote them: my early ones were tours of my intended implementation. The useful ones are structured around the decision: the problem, the constraints, two options, the one I recommend and why, and what would change my mind. People can engage with that. Nobody can engage with a wall of architecture.

Making decisions legible matters more than the code itself. Every significant choice I make now leaves a trail someone can audit later: a short ADR, a PR description explaining why rather than what, a summary after a hallway decision so it exists somewhere searchable. This felt like overhead until the first time a teammate extended my system correctly without asking me a single question. The reasoning was sitting right there. Writing things down isn’t documentation; it’s how your judgment scales beyond your own keyboard.

Tooling shifts have made this even more true. As I wrote in how I use AI coding assistants, the mechanical act of producing code keeps getting cheaper. Judgment about what to build, clearly communicated, is the part that doesn’t commoditize.

Force multiplication

The accounting change finally made the senior role make sense to me. As a mid level engineer, my impact was roughly the sum of my commits. As a senior engineer, it’s measured across the team, and that math has a ceiling problem. I can maybe get 20% better at writing code year over year. But if something I do makes six teammates 10% more effective, that dwarfs anything I can produce alone.

In practice, force multiplication looks mundane:

Code review turned into teaching. I used to review for correctness: catch the bug, approve, done. Now I review for transfer. If I know something the author doesn’t, the comment explains the why, links to the relevant pattern, and distinguishes “blocking” from “take it or leave it.” A review that only fixes this PR is a transaction; one that changes how someone writes the next ten PRs is an investment.

Unblocking became a priority instead of an interruption. The naive calculation says helping a stuck teammate costs me an hour of my project. The real calculation includes their next three days. I treat “who is stuck?” as a standing daily question, and I drop focused work for it more often than my calendar would prefer.

Mentoring meant delegating the interesting stuff. The failure mode is hoarding the fun problems and handing off only grunt work, which feels efficient but caps the team’s growth. The discipline is handing someone a problem slightly too big for them, letting the solution be theirs, and staying close enough that they can’t fall far. It’s slower this quarter and faster every quarter after.

None of this appeared on my ladder rubric in these words. But what actually gets people promoted and trusted is this: engineers around them get better, and messes near them get smaller.

How to practice before you have the title

Almost none of this requires permission. Titles lag behavior: every promotion I’ve watched went to someone already doing the job. What I’d practice:

  • Volunteer for one vague thing. Find a problem everyone complains about and nobody owns: flaky tests, a slow build, a confusing onboarding doc. Run the scoping pattern above on it. Small ambiguous problems are reps for big ones.
  • Write one design doc for something you’d normally just build. One page. Problem, options, recommendation, what would change your mind. Ask for review. The first will be awkward; the fifth will change how you think.
  • Follow one shipped feature for a month. Check the metrics. Read the support tickets. Ask whether it actually did what it was supposed to. Nothing rewires task thinking into outcome thinking faster.
  • Upgrade one code review per week. Pick a PR and review it like a teacher instead of a linter: explain reasoning, link references, praise something specific.
  • Write down a decision that currently lives in your head. Any one. Put it where the team can find it.
  • Build something end to end where every call is yours. This is a big part of why I ship side projects: a solo project forces you to scope, decide, cut, and own outcomes with nobody upstream to hand you a ticket. It’s the whole senior loop in miniature.

Pick two. Do them for three months. That’s it: that’s the actual answer to how to become a senior software engineer, and it’s boringly unglamorous.

FAQ

How many years does it take to become a senior engineer?

It varies too much for the number to mean anything. I’ve seen it happen in four years, and I’ve seen engineers with fifteen years who never made the shift: years measure exposure, not the transition this post describes. What matters more is whether you’re already operating at the next level: owning outcomes, absorbing ambiguity, multiplying others. When the answer is visibly yes for a sustained stretch, the title tends to follow. If not where you are, then somewhere else.

Do I need to work at a big tech company?

No. Big companies offer scale problems and calibrated ladders; small companies offer something arguably better for this transition: ambiguity and ownership by default, because there’s nobody else to hand the vague problems to. Worry less about company size and more about whether you get to own something whole. If every problem reaches you already broken down, that’s the thing to change.

Is the senior title the same everywhere?

Not even close. “Senior” at one company maps to mid level at another and staff at a third, and title inflation makes cross company comparison mostly noise. What transfers is the capabilities, not the label: scoping fuzzy problems, writing decisions people can follow, making a team better. Those travel everywhere. Optimize for them and treat the title as a lagging indicator.

What I’d tell my mid level self

The move from mid level to senior engineer isn’t a reward for accumulating technical depth. Depth is table stakes, and it’s rarely the bottleneck at that stage. The bottleneck is the identity shift: you stop completing tasks and start owning results, you stop waiting for clarity and start manufacturing it, and your output stops being code and becomes a more effective team.

If you’re asking how to become a senior software engineer, the answer is that you start doing the senior job before anyone calls you senior, in small unglamorous reps, until the title becomes a description rather than a goal. It’s slower than grinding leetcode and less visible than shipping features. It’s also the only version of the path I’ve actually seen work.

Get new posts in your inbox

No spam, no fluff: one email when I publish something worth your time. Unsubscribe anytime.

Signup opens soon. Grab the RSS feed meanwhile.

Keep reading