The path to becoming a Senior Engineer

The path to becoming a Senior Engineer

A natural step in the career of every software engineer is the transition to a senior role. Easier said than done, I see this step posing a challenge to a lot of engineers - that's why I want to write about what is expected from senior engineers and practical tips to help you on this journey.

I want to preface this article by saying that I will use the term senior loosely in the paragraphs below. When I say senior I'm referring to the range of senior to staff engineer, but closer to the senior side rather than staff/principal. Staff engineers have additional responsibilities which we won't cover in this article, but a lot of principles carry over between levels. You can think of an L5/L6 at Google or E5/E6 at Meta, which would be very close to this definition.

What is a senior engineer anyway?

Let's first need to define what a senior engineer is. Here is how I think about it:

💡
A senior engineer is a technical partner for management and someone who other engineers come for advice.

I know this is somewhat vague and generic, but it captures the essence of what it means for me to be a senior in software engineering.

A technical partner for management means someone who contributes to the success of the team, product and business from a technical perspective - this can be anything from planning and estimating big projects, helping define the roadmap for your team/group in the next 6-12 months, assessing impact and risk of changes, etc.

Someone who other engineers come for advice implies technical expertise, mentorship and communication. It means that you are recognized as an expert by folks in your team and more importantly, you are someone they want to work with.

That being said, let's try to look at some of the key areas you should focus on if you want to get to that senior position.

Ownership

If you walk away with just one idea from this article, let it be this - ownership is the single most important trait that defines a senior engineer.

An engineer is displaying ownership when they feel accountable for their work and they take responsibility for the outcome of that work. For me personally, this is a fundamental trait that predicts a successful career and I value it higher than anything else.

Ownership = Initiative + Care

An oversimplification to be sure, but one that I found to make sense for me. Ownership usually starts from a place of caring - caring about your code, the product you're building, the users of your product, your team and many other aspects.

Here are a few instances that illustrate this:

  • Creating a script to automate the development environment setup, so other engineers don't spend hours typing in terminal commands by hand.
  • Getting that unit test coverage up to 95% so that others can come in and contribute to the code base with confidence.
  • Optimizing that API call to return in 50ms instead of 200ms, so that the users of your app can have a nicer experience.
  • Tearing down that cloud resource that nobody uses anymore to save the company a bit more money (which can be used in your next experiment).

These are just a few examples, but you get the idea. Owning something ultimately means taking initiative because you care about what you're doing and the people around you. And if you care, you will succeed.

Ownership is infectious

Like Eric Rabinovich writes in this article, ownership has a parasitic nature. If you are passionate about what you do and really care about stuff, soon you will start to care about other things as well (and possibly become their owner). A simple example is testing - engineers who take ownership of their code also care about testing that code. They don't say "It's the QA team's job to test", they put their testing hat on and start thinking of ways in which the code may fail, after which they start writing tests.

Take the first steps towards becoming an owner and I can guarantee you that it will have a multiplicative effect on your growth and career.

Taking ownership

The thing with ownership is that nobody will come to you and say "Hey, do you want to be the owner of this?". Owners are leaders who come in and say "I am responsible for this thing" or better yet, they demonstrate it by consistent action. That's why we say that ownership is not given, it's taken. A few tips for taking ownership:

  • Say Yes - Never say no to a request just because you have a lot to do. Try to be involved in as many things as possible, while maintaining efficiency. So the next time someone asks your help with a ticket, a presentation that needs to be done or a production issue that needs to be investigated - say yes and go do it. You will gain more context, visibility, respect from your peers and be recognized as someone who gets things done. I highly encourage you to read David Allen's book on how to get things done.
  • Provide solutions - When there's a problem to be solved or you notice something that can be improved, take some time and try to come up with a solution. The solution doesn't need to be perfect, it just needs to start a conversation. Start with something simple such as working with QA on test-cases. Even if your solution is sub-optimal or it doesn't get prioritized, it doesn't matter - you will still be seen as someone who is taking initiative and cares about things. As usual, pick your battles here - you won't have time to come up with a solution for everything, so use your best judgment.
  • Work with management - Your manager and the folks in management roles should be your allies and partners, not people who tell you what needs to be done. Discuss with your manager to understand the roadmap and business context of your work. Review that roadmap and provide feedback if you notice something that is not feasible. Think if the projects on the roadmap can be optimized in terms of sequencing and dependencies. Add any enhancement or maintenance projects that you know should be done sooner rather than later. Help them in understanding the technical aspects and consequences of the choices being made.
  • Engage with other technical experts - Not just in your team, but other teams and departments as well. Join the conversation when another team presents a cool new feature they've developed. Reach out to folks and get their feedback on things your team is doing. Ask a senior engineer from another team to give you a short overview of something they built and you find interesting - most of the time they will be more than glad to do so. Try to get out of your comfort zone and engage with folks from other disciplines - sales, marketing, HR, support, etc. You will find their perspective invaluable in your growth as a professional.

In his book Turn the Ship Around David Marquet speaks about the concept of leader-leader, which challenges the traditional view of leaders and followers. Instead of delegating responsibilities, Captain Marquet empowered the crew to develop proactivity and ownership and as a result, folks embraced playing to their strengths and became an effective, high-performing crew. Marquet speaks about intent-based leadership, which is something I highly encourage you to think about. Instead of being passive and unsure by asking questions such as "Do you think this is a good idea?" or "Can we do this?", think of solutions and rephrase these questions with "I intend to...". This puts the responsibility of the decision on you, with your manager simply approving (or not) your idea. But it's also a very effective way of changing your perspective and taking ownership.

Technical prowess

A senior engineer is an engineer at heart, which means building software is one of your primary functions. You are expected to write high-quality code with almost no guidance, which is no small feat!

80% depth, 80% breadth

What engineer didn't want to be a master of their chosen programming language? To know the intricacies of every feature of that language and to be able to write optimal code each time. While that's noble, in practice I've found that it doesn't matter as much if you're a blackbelt Java programmer or a master at solving dynamic programming problems - what really matters is understanding each of these tools enough and having the breadth of knowledge to help you make the best decisions in the context of complex systems.

This is not a hard and fast rule though. Some things will require that you have a deep understanding of what a particular technology has to offer. Those circumstances will be self-evident though - if you're building a managed service on top of Kafka, you will need to know everything Kafka can do. But in many cases, a software product involves many different tools, technologies, frameworks and architectural patterns. In those cases, it's far more beneficial for you to become comfortable with as many of them versus focusing your attention only on a couple. That's why I say 80% depth - you should have a solid working knowledge of the tools that you're using, but it's not efficient to aim for 100% expertise in everything. That extra 20% usually involves an additional 80% effort.

You are much better served by developing your toolset as an engineer. Learn about clean code, efficient algorithms, operating systems, databases, APIs, deployment, testing, observability, etc. You won't be able to be proficient with all the parts that make up a modern application but focus on getting that 80% breadth - the tools that you see being used again and again.

The only tip I can give you here is to be curious. If you see something new, ask about it. Go and look it up on stack overflow. Read books on the subject. Together with ownership, curiosity is a very important characteristic of senior engineers.

Focus on quality

Nothing says senior more than high-quality code. While more junior engineers tend to move fast and break things, seniors are known for predictable and drama-free deliveries.

Senior engineers know that software development is a marathon, not a sprint. There will always be new things to do and solve, so your work is never done. That's why it's very important that once you deliver something, you know that it's done - you're not coming back to it unless the requirements change.

Here are a few ways of doing it:

  • Don't skimp on code reviews - Aim to have at least the service/code owner as a reviewer and an additional engineer, if possible. Two reviewers give you the best chance of successfully landing your change in production.
  • Spend time in design - Resist the urge to jump in the code, take some time to do proper design. In my experience, good engineers spend more time on design than actually coding.
  • Test more - Be adamant about testing, don't just assume things will work. Unit tests and integration tests should be done by you. Work with test engineers to develop non-functional tests as well (load, resiliency etc.). Consider A/B testing whenever possible. There's no such thing as too much testing.
  • Plan & estimate - Get better at planning and estimating your work. Always have a 10-15% time buffer for handling unforeseen issues (which always show up).
  • Manage risk - Think about what can go wrong and how to mitigate it. Consider any dependencies on other teams and try to minimize that, if possible.

Innovate & Improve

As a junior or middle-level engineer, you are expected to work on well-defined features with clear expectations. But as a senior, you are also expected to innovate and improve the product that you are working on. This can be anything from using a more efficient algorithm for data processing or improving build times to things like optimizing the infrastructure costs of your services. It's hard to give tangible advice on this, but here are a few tips that can help:

  • Stay up to date with industry trends - This involves reading books, articles and other forms of content to keep a finger on the pulse of the specific industry you activate in. A few that I used to read on a regular basis:
  • Don't take things for granted - Just because your company used MySQL for most projects, it doesn't mean that it's the right choice for your project. Think things through to see if they make sense. Constantly ask why. Challenge decisions that are made without a thorough analysis.
  • Allocate time for innovation - It's very hard to improve things if all you do is code feature after feature. You need to leave room to think about innovation. Start with 5% of your time and look at small improvements. Increase that percentage over time as you grow into a senior role.
  • Control technical debt - I've seen many teams that needed to take a big break from feature development in order to address the increasing technical debt. I was once part of a team that spent over 6 months getting things under control. Don't be like that - a good senior knows to keep things in check by continuously taking things from the backlog and prioritizing them. Nobody is going to come to you and say "We have enough time to work on backlog items", it just doesn't happen in the real world. Instead, you need to proactively identify the things that need attention the most and include them in the planning for the next 3-6 months.

Dealing with the unknown

One of the harder things senior engineers do is handle the unknown - and believe me, there is a lot of ambiguity and uncertainty in building software products. As hard as it is sometimes, it's a very important skill to master on the path of becoming a senior engineer and it will serve you well throughout your career.

When things are ambiguous or it feels that nobody knows what to do, it can feel frustrating and even demoralizing at times. You might consider that it's not your job to figure these things out. Well, I'm here to tell you that it is - as a senior engineer, folks look to you for providing guidance and solutions.

How many times have you heard things like "We need to build X feature", "Customers have Y issue in production", "This is the requirement from PM, let's build it" or "Our alerts seem to be flaky"? It's part of our daily lives as engineers and an even bigger part when you're a senior engineer. Even though the problems are very different, I have a mental model that can help you in dealing with whatever comes your way.

Let's go over each of them:

  • Issue - It all starts with a problem to solve, something that doesn't have a clear set of requirements.
  • Own - The first (mental) step is to take ownership over the situation. You are going to solve or help solve this issue.
  • Clarify - Before solving anything, you need to get clarity over the current state of the problem. Ask all relevant stakeholders what are they trying to achieve.
  • Align - After getting clarity on the problem, it's time to align with the stakeholders. Have everyone agree on the next steps and assert your intention of taking ownership of part or all of them.
    • Prioritize - Complex issues usually involve a lot of parallel threads. Make sure you are focusing on the most important ones.
    • Delegate - If you feel you don't have enough time to handle everything, ask for help or delegate whenever possible.
    • Manage risk - The first thing in tackling each task is identifying potential risks. Communicate them upfront and try to find ways of mitigating them.
    • PoC - Many times before coming up with a complete solution, doing a small proof-of-concept is usually a good idea for confirming your assumptions and addressing any risks.
    • Get feedback - After you have something done, ask for feedback. Do this as early as possible. Incorporate that feedback in your final proposal.
    • Propose - Write up a proposal for solving the initial issue and present it to the relevant stakeholders. The next step is alignment, as this is an iterative process until you reach a final solution.
  • Execute - Once everyone is aligned and agrees on the solution, begin the actual execution phase. You can work together with other engineers on this, but you are the de-facto owner of the solution, which means you will be held accountable for its success or failure.
  • Solve - If everything goes well, at the end of the execution phase, you will have solved the original issue.

This model might seem complex at first, but it's usually straightforward in practice. Let's see it in action in a couple of real-world examples.

  • Code reviews are taking too long
    • Own - Firstly you decide to do something about it because it's slowing down your team's cycle time.
    • Clarify - You gather information from the team and find out that you don't really have an agreed coding style, which is making these reviews subjective.
    • Align - Get the team together and mention that you want to come up with a proposal for a coding style and best practices.
    • Prioritize - A full-fledged coding style document could take a long time, so you decide to focus on project structure and variable naming first, things that you noticed caused the most comments.
    • Delegate - You ask another engineer if they would be interested in helping with writing about the comments section.
    • Manage risk - Not applicable here.
    • PoC - You do a small write-up in a Google doc and immediately share it with the team.
    • Get feedback - You ask the team to give feedback on the above document. You also send it to a couple more senior engineers from other teams.
    • Propose - After finishing the write-up, you gather the team again and present your final proposal. Address any feedback using the same process.
    • Execute - In this case, it just means publishing the doc and sending a notification message to let everyone know you will be using this coding style from now on. Maybe it also means enforcing this via an automated tool in your CI/CD pipeline.
  • New customer feature request
    • Own - You look at the ticket as part of your regular triage process and identify that it's something that could be valuable for other customers as well.
    • Clarify - You work with the support engineer who reported this issue and the PM of the product to understand the needs of the customer.
    • Align - You let your manager and team know that you will be working on this ticket. You present a high-level plan with the next steps in the process.
    • Prioritize - The first thing you decide to do is to understand the performance impact of adding the new functionality into the product.
    • Delegate - You realize that the work cannot be parallelized, so there is nothing to delegate.
    • Manage risk - In your design, you identify that the database might not support the additional load from the new feature, so you decide to do a PoC to test this assumption.
    • PoC - You work on a small PoC for testing the database performance.
    • Get feedback - After you have some numbers from the PoC, you present them to a principal engineer in your team and get their feedback.
    • Propose - You write a design doc, describing the changes and new data flow in the system after implementing this feature. You present it to the team, your manager, the PM and other relevant stakeholders in order to get their buy-in.
    • Execute - You implement the changes described in the design doc.

Mentorship

The best engineers I know are good mentors. They view mentoring others as an integral part of their job and they jump on the opportunity to teach other engineers and see them succeed. Mentoring can be done at any level, but it's expected from a senior engineer.

There are two types of mentoring that I've seen in my career:

  1. Formal mentoring - When a more senior engineer agrees to serve as a mentor for a more junior engineer as part of a formal program in the company. The program is usually time-bound to several months (even longer sometimes) and has well defined goals for both the mentor and the mentee. More common in big tech companies like Facebook, Google, Uber etc. and less common in start-ups.
  2. Informal mentoring - The most common form of mentoring, it happens all the time between engineers through code reviews, technical sessions, pair programming, etc.

If you can join a formal mentorship program, I highly encourage you to do so - it's a great opportunity to develop your skills, either as a mentor or mentee!

Tips for mentoring

Here are some things that worked for me as a senior engineer:

  • Define clear goals - Even informal mentoring needs goals, otherwise you won't know if you succeeded or failed at the task. Goals should be discussed between the mentor and mentee and confirmed with the mentee's manager. This can be something as simple as becoming proficient in a specific programming language or as complex as learning to design the architecture of a mobile app that has 100M users. I would encourage starting with simple goals that can be achieved in 3-6 months.
  • Constant reviews - Be it code reviews, design reviews or documentation reviews, focusing your attention here is one of the best uses of your time as a mentor. The point of these reviews is not to criticize the mentee's work, but rather have them learn and improve. Be patient in understanding what they're struggling with and gently guide them to identifying the optimal solution on their own. Don't just answer their questions, try to give them more context to stir their curiosity and help them connect the dots in the future.
  • Pair programming - One of the most powerful tools to have in your arsenal, this is essential for being a great mentor. The pair programming sessions are a chance for the mentee to see how you work, ask you questions on the spot and observe unconscious patterns that you might miss in your day-to-day. It's also an opportunity for the mentee to see your thought process for solving real-world problems, which is invaluable for them.
  • Give context - You should be proactive as a mentor. Share any internal or external resources that you found useful with your mentee. Involve them in different technical discussions as an observer. Send them links with various news in the company or the tech industry.
  • Feedback - A final tip is to always be giving feedback to your mentee, both positive and constructive. Celebrate their learnings and victories but also tell them when you see something that can be improved. Well delivered feedback is one of the most important things you can do as a mentor.

A hallmark of a senior engineer is growing the team around them. Be a mentor for others and you'll learn a lot and grow yourself in the process as well.

Impact

An important metric that's usually looked at for senior engineers is their impact. Impact means what is the output of the work you're producing as a function of the time invested. A very good book on the subject and one I highly recommend is The Effective Engineer. Edmond Lau suggests in the book that we focus on what he calls high leverage activities, which just means prioritizing activities that generate a large impact for the amount of time you're investing.

Feedback loops

It's hard to measure impact unless it's something very specific. That's why I recommend setting up multiple feedback loops to help you understand the impact of your work. I recommend having at least two:

  • Product - Get a sense of the product needs by discussing with Product Managers, sales engineers, support, marketing etc. Basically folks who can tell you if the work that you are doing is truly helping to solve real problems for customers, be it internal or external. Align with them regularly and get their input on what really matters and adjust your plan accordingly. I suggest scheduling a regular sync with your PM once every 2 weeks.
  • Technical - Try to get in the habit of having other engineers review your work, be it code, design docs, feature proposals etc. Aim to leverage the knowledge of other senior engineers to give you an indication that you are going on the right track. Ask input from engineers working on different teams, which oftentimes offers you a different perspective on things.

To understand the impact, you need to take a step back and look at the bigger picture. If you're just heads-down coding all day, you might build a very good product that nobody will use. Getting a big picture view is the end goal of the feedback loops.

You can also look at impact in terms of layers. The image below shows the most common layers you will need to work towards in your journey to become a senior engineer. As you can see, the code is just a piece of the puzzle in the larger architecture, which itself is just a part of what constitutes a good feature. My advice to you is to focus on each of these layers but try to look beyond and see how your work fits into the larger scope. Having this vision will allow you to make more strategic decisions and will ultimately make you a better engineer.

Impact radius

Communication

I purposefully left communication last, because it's maybe the hardest to explain and give tips about, but at the same time, it's the glue that binds all of the aspects discussed above.

One of my favorite quotes on communication comes from George Bernard Shaw:

The single biggest problem in communication is the illusion that it has taken place.

There's a very "simple" way of fixing this and it's my biggest tip for you on this subject - overcommunicate. I cannot emphasize enough how often I've seen engineers not use this concept, so I highly encourage you - don't skimp out on communication in all forms, I can promise you that it's going to pay big dividends in the long run.

Many books have been written on this topic, so I will limit this paragraph to giving you real-world examples of how you can work on your communication.

Verbal communication

By verbal communication, I mean any form of meeting, be it in-person or online. Even though the last couple of years have made it so we don't rely on this method of communication as much as we did before, it remains a very important tool to leverage as an engineer.

Tips for improving your verbal communication:

  • Use it sparingly - There are many things which can be solved without scheduling another meeting and you should think carefully if you really need one.
  • Prepare - The most important advice I can give is to come prepared for every meeting. Be it a regular sync meeting, a 1:1 with your manager or a big presentation with a large audience, spend time preparing each one. I create a small to-do to remind me to have some notes ready before each meeting. This goes double if I'm the host.
  • Actively listen - I know you've heard this one before, but the truth is that many of us are very poor at actively listening in meetings. Try to really listen to what people are saying and ask clarifying questions when needed. A useful tip is replaying what other people are saying when you want to get alignment on a topic.
  • Practice - Last but certainly not least, being a good communicator takes a lot of practice. Take some time to rehearse your speech before a meeting with a large audience - I once practiced for 4 hours to deliver a 20-minute speech! Look for opportunities to practice your verbal communication - offer to hold presentations whenever possible, volunteer to be a buddy for a new hire, take initiative and speak for 75% of the time in your next 1:1 with your manager. I know it's sometimes uncomfortable but seek out any opportunity to work on your delivery and your communication skills will surely improve.

Written communication

This includes instant messages, documentation pages, tickets and all sorts of documents that you write on a regular basis. This method of communication is becoming more and more important with the rise of distributed teams. It's not uncommon to have software teams with a 10h time zone difference and written communication is becoming an essential tool for working effectively.

Here are a few things that I personally use and have found effective:

  • Use design documents - Many times software design is an iterative process and having a live document ensures that you have a good chance of converging to an optimal solution. Put as many details, questions, proposals or open items in there. Start early (even in the research phase) and ask for feedback from your peers. The design doc doesn't need to be anything fancy - just a simple Wiki page will do. Make sure you have a structure for creating them, so folks can find them easily. This is the single most effective tool that creates high-performing distributed teams. Gergely Orosz has a good article on this topic.
  • Give constant updates - Be it on instant messaging tools like Slack or project tracking tools like Jira, make it a habit of letting your team know of your progress. Update the Jira tickets at least once every 2 days. When you log off at the end of the day, post a small update in your team's Slack channel - this way your peers who are maybe just logging in will get some context and can maybe continue your work. Don't overdo it, you don't need to provide updates on every small thing, but rather think if you can unblock yourself or someone else. If you're in doubt if you should provide an update or not, do it - remember to overcommunicate.
  • Document processes - I can't stress enough how important is to write down the (technical) processes that your team uses. I don't even want to think how many countless hours are spent and how many mistakes get made in teams that don't take this seriously. Processes can include things like:
    • Onboarding for new hires
    • Building and deploying the code
    • Coding style and best practices
    • Service runbooks
    • Running test suites
    • Debugging common issues
  • Keep things up to date - I know that keeping documentation up to date is one of the hardest things to do consistently, but trust me - it's well worth it. There's no magic formula for this, you just have to dedicate a bit of your time to make sure the technical docs are up to date. The easiest way of doing it is to allocate explicit time during project planning and update things along the way. It's incredibly difficult and error-prone to update everything at the end.

Conclusion

This article only scratches the surface of what it means to be a senior engineer. There are a lot of things that can be said on the subject, but I want you to walk away with this:

💡
Being a senior is more of a mindset than anything else. Take ownership, be curious and help others and you will be well on your way to becoming a senior engineer.