← Back to list

I made senior in year three. The staff engineer who sat next to me showed me

What got me to senior was not going to get me to staff. The behaviors are different.

Devrim Ozcay — Production Engineering in CodeToDeploy · 2026-06-22 02:23 · 50 claps · 9.8 min read
#coding #software-development #software-architecture #web-development #software-engineering
Open on Medium ↗
Wiki topics: 💻 · Programming 🌐 · Web Development 🏛️ · Architecture

I made senior in year three. The staff engineer who sat next to me showed me there was another level I had not started thinking about.

What got me to senior was not going to get me to staff. The behaviors are different.

I made senior in year three. The title change felt like an arrival. My pay went up, my scope expanded, my opinion carried more weight in design reviews. For about twelve months, I assumed I was just going to keep doing more of what had gotten me promoted and the next title would follow.

🚀 Get Hired Faster

Find jobs, build a professional resume, and land more interviews.

It did not follow.

The pattern at year four was uncomfortable. I was shipping more, getting better reviews, more visible, more trusted. The next promotion conversation in my 1:1 went the same way every quarter. “You are a strong senior. We are not sure yet what your staff-level case looks like.”

I had no idea what they meant. I thought “staff” was just “really good senior.” I started watching the staff engineer who sat next to me to figure out what was different.

What I found was that nothing he did looked like more of what I was doing. He did completely different work. The work was harder to see because it did not produce visible output in the same way a sprint commit does. But once I started looking for it, his patterns were everywhere, and I had not been practicing any of them.

These are the five behaviors I now copy. They are what I am still working on at year five. I am not staff yet. I am closer than I was.

One. He built artifacts that compounded across the team.

I shipped code. I shipped pull requests. I shipped features. At the end of every sprint, I could point at the work I had produced. The work was real and valuable. It also had a half-life. The feature I shipped this sprint was last sprint’s feature next sprint, fading into the background of the codebase.

He shipped artifacts that did not fade.

The most concrete example was a one-page document he wrote in his first month on the team. It was called “How we make architectural decisions on this team.” Two pages. Three sections. It defined what counted as an architectural decision, what kind of RFC was required, who needed to approve, and what the rollback expectations were. It took him probably four hours to write. It was the most-cited document on the team for the next two years.

Every architectural conversation on the team after that point started by referencing his document. New engineers were given it in their onboarding. When a junior engineer wanted to make a change that crossed a boundary, the senior who reviewed their PR would ask “did you read the architectural decisions doc.” When a staff engineer from another team wanted to coordinate on a shared piece of infrastructure, our team would point at the doc. The doc compounded its own value every time it was read.

I had written a similar volume of code in the same period. Not one of the things I had shipped had this kind of half-life. The code I had written was tied to specific tickets, specific features, specific moments. His document was tied to the team’s permanent ability to make decisions.

I started writing artifacts. Onboarding docs. Decision frameworks. Postmortem templates. Most of them did not stick. The ones that did stick I could not have predicted in advance. The pattern was that I had to write more than I would otherwise, knowing that most of it would not compound, in order to write the small percentage that did.

Two. He redefined the problem before solving it.

The product manager would walk in with a request. “We need to support multi-currency payments by the end of the quarter.”

I would hear the request and start thinking about how to solve it. Database schema changes for currency fields. Exchange rate handling. Reporting. Display logic. I would come back with a scope estimate and an implementation plan. I was solving the problem I had been given.

He would hear the request and ask one question. “What are users actually telling you that made this come up?”

The product manager would explain. Three enterprise customers had asked for the ability to bill their European subsidiaries in euros. Two of them had asked about specific currencies that were not euros. The actual customer need was not “multi-currency payments.” It was “enterprise customers want to bill their international subsidiaries in their local currencies.” The two problems sounded the same. They were not.

The staff engineer pointed out that “support multi-currency payments” was a system-wide change touching invoicing, reporting, settlement, and tax. The actual need could be met with a per-customer setting that let an enterprise pick the billing currency for each subsidiary, with no change to the underlying system, in two weeks instead of six months. The product manager left the conversation with a scoped-down ticket that delivered exactly what the customers had been asking for.

I had been answering the question as asked. He had been treating the question as the symptom and looking for the actual requirement. This single behavior, repeated, was responsible for an enormous amount of his impact. He delivered less code than I did. He delivered more value because the things he delivered were closer to what customers actually needed.

Three. He built paved roads, not one-off solutions.

We had to add observability to a new service. I built it the way I had built it on the previous service: Prometheus metrics, custom dashboard, manual alert configuration. It worked. The service was observable.

He had been asked to do the same work on a different service two months earlier. He had not built the observability for his service. He had built a library that any service could import to get a standard set of metrics, a standard alert configuration, and a standard dashboard auto-generated. The library was three hundred lines of code. Adding it to a service was four lines.

His library was already used by four services when I started observability work on mine. The reviewer of my PR asked why I was building it the manual way when the library existed. I had not known the library existed. I added it to my service in twenty minutes. The whole one-week ticket collapsed to twenty minutes because someone else had built the road.

This was the pattern across his work. When he had a piece of work to do that he suspected would be needed again, he made the work reusable as part of doing it. The first instance took him 1.5x longer than the manual version. By the third instance, he was done in a tenth of the time, and so was every other engineer who used it after him.

I had been treating each ticket as standalone. He had been treating each ticket as either a one-off (just solve it) or a precedent (solve it in a way that scales to the next one). The difference was a judgment call he made consciously every time, and it was responsible for half of the leverage difference between us.

Four. He had opinions on what the team should not be doing.

I had opinions about how to do the work that landed on my plate. I was good at design reviews. I was good at evaluating tradeoffs once a problem was scoped. I was not good at the level above that.

He had opinions about which problems the team should be picking up at all.

In the quarterly planning meeting, I would advocate for the technical choices within the projects that had already been selected. He would advocate for or against the projects themselves. “This one is a six-month investment for a problem that affects two customers. The other one is a two-month investment for a problem that affects half the user base. We should swap them.” He had a perspective on the team’s strategic scope, not just its tactical execution.

The first time I watched him say “I do not think we should be doing this” in a planning meeting, I was uncomfortable. He was a senior engineer pushing back on a project the engineering manager had already proposed. My instinct would have been to find a way to make the project work. His instinct was that the team’s time was the most expensive resource, and using it on the wrong project was the most expensive mistake the team could make.

The director in the meeting did not push back. The director listened, asked a few questions, and reshuffled the quarter’s priorities. The staff engineer’s opinion had moved the team’s strategic direction. Not by demanding it. By having a clear, defensible view of what the team should not be doing, and being willing to say it out loud in the right meeting.

I had been operating one level lower. I optimized within the constraints. He was the one moving the constraints.

Five. He made other engineers more effective.

I shipped my work and I shipped it well. I helped teammates occasionally, when asked. My code review comments were sharp. I was a contributor.

His ratio of helping others to shipping his own work was upside-down compared to mine. He spent more time in other people’s pull requests than his own. He paired with junior engineers on debugging problems for an hour at a time. He wrote design documents for projects he was not on, just to unblock the team that was on them. The first time I noticed, I thought he was being inefficient. Then I tracked the team’s output over a quarter.

The team shipped more when he was around than when he was not. Not because he shipped more code. Because everyone else shipped better code, faster, with fewer revisions, with fewer incidents. He was a multiplier. His personal output was lower than mine. His impact was higher than mine by an enormous margin.

I had to update my mental model of what “productivity” meant at the staff level. It was not about how much code you personally wrote. It was about how much code the team around you shipped that was better because you were on the team. The work was hard to see because most of it happened in pull requests with other people’s names on the commit. The impact was measured at the team level, not the individual level.

The connecting thread

Each of the five behaviors had the same shape. He was operating at a level above the work itself. Writing artifacts about how the team made decisions instead of just making decisions. Redefining problems instead of solving them. Building roads instead of walking them. Having opinions about strategy instead of execution. Making teammates better instead of contributing more himself.

Senior engineers are measured by what they ship. Staff engineers are measured by what their team and adjacent teams ship that is better because they exist. The promotion criteria are different. The behaviors that get you the promotion are different. The work that produces the impact is different.

I had been trying to get to staff by being a better senior. The path to staff is not “more of what I am doing.” It is a different category of work.

What I am working on now

I am at year five. I am not staff yet. I am closer than I was. The behaviors I have made the most progress on are the artifacts that compound (I now write more onboarding docs, decision frameworks, and post-mortems than I used to) and the paved roads (when I build something, I ask whether the next engineer who needs it should be able to use what I built without learning it from scratch).

I am still bad at redefining problems. I default to solving the question I was asked instead of questioning the question. I am still bad at having strategic opinions about team scope. I do not yet feel the right to say “we should not be doing this.” That muscle is harder to build because it requires being willing to lose those arguments and damage trust if I am wrong.

The leverage on the staff transition is in the behaviors I am the most uncomfortable with. That is probably not a coincidence.

Where the rest of this is written down

I documented twenty career-shaping moments in backend engineering work. The deployment decision where the junior path looks safe and the senior path is to delay one day. The architecture review where the junior path is to defend your design and the senior path is to update it. The incident postmortem where the junior path is to blame the on-call and the senior path is to identify the system gap. The promotion conversation where the junior path is to list what you shipped and the senior path is to name the decisions you owned. The same lens applied to the staff-level moments is what I am working on now, but the senior moments are the floor that has to be in place first.

It is the Senior Engineer Playbook. It comes bundled with three other PDFs: the 02:43 Outage incident decoded minute by minute, a Backend Architecture Decision Playbook covering eight tradeoffs that compound for years, and a Code Review Playbook with twenty patterns I check for now in every PR.

The gap between mid and senior is the gap between executing well and making good decisions under pressure. The gap between senior and staff is the gap between making good decisions and reshaping what decisions the team is making. They are different skills. The first is taught by enough reps. The second is taught by watching someone two levels above you operate, and by deliberately practicing behaviors that feel uncomfortable until they do not.

I am not done. The staff engineer next to me retired six months ago. The person who replaced him operates differently and is teaching me different things. The list of behaviors I am still working on is longer than the list of behaviors I have built. That used to bother me. Now I think it is the point.

Thank you for being a part of the community

Before you go:

👉 Be sure to clap and follow the writer ️👏️️

👉 Follow us: **Linkedin| [Medium](https://medium.com/codetodeploy)**

👉 CodeToDeploy Tech Community is live on Discord — **Join now!**

Disclosure: This post includes affiliate and partnership links.


메타데이터
post_id
37cfd4b904e5
slug
i-made-senior-in-year-three-37cfd4b904e5
url
https://medium.com/codetodeploy/i-made-senior-in-year-three-37cfd4b904e5
canonical_url
https://medium.com/codetodeploy/i-made-senior-in-year-three-37cfd4b904e5
author_url
https://medium.com/@developer_programmer
status
ok
fetched_at
2026-06-23 03:48:11