Software Engineering Levels
Software organizations are founded, restructured, and dissolved every business day. There are many public software engineering career ladders. “Senior” developers in some organizations have skills that would be considered below entry-level in others. This document details a framework for growing and evaluating software engineers derived from my experience as an engineering leader. Here we consider underlying capabilities:
- owning relationships
- making technical sense
- humility towards reality
and show how they map to an idealized career ladder: Apprentice, Core, Senior, Staff, and Principal, each of them a Member of Technical Staff. Across industry those labels are attached to a wide variety of skill sets. Our purpose here is to understand archetypes rather than commit to job descriptions.
This discussion is drawn from my experience in rapid-cycle, team-oriented organizations where individual accomplishment embodies a core tension: the fundamental unit of software delivery is the team, but individuals compose those teams and achieve results through them. The quality of individuals’ relationships with their teammates is thus a primary factor in their team’s productivity, and a primary responsibility of every engineer. My teams have shipped technically ambitious new systems under deadline and quality pressure not despite interpersonal dynamics, but because of them.
Owning Relationship Halves and Wholes
Every team of N people has N(N-1)/2 two-person relationships, each comprising two halves: how A relates to B, and how B relates to A. While no actual 8-person team maintains 28 exemplary relationships, engineering management must recruit individuals who relate productively to one another. Over time, a team composed of:
- 10 strong, 12 adequate, and 6 mediocre relationships
will sharply outproduce the same collection of individuals having:
- 12 strong, 6 adequate, 4 mediocre, and 6 damaging relationships
Therefore, owning relationships is a primary responsibility for all developers:
-
Apprentices own their professionalism and effort, but may not yet own their half of a relationship. For example, they might silently struggle with unexpected friction rather than proactively flagging the delay to a leader.
-
Core developers own their half of every relationship and maintain useful mental models of key colleagues. They engage effectively provided the other party does the same. When reviewing a flawed pull request, they:
- Recall this is the engineer’s second similar error recently
- Acknowledge that the engineer has been under unusual strain
- Calibrate their feedback to address the problem while respecting their colleague’s current context and familiarity with team cues
-
Senior and Staff developers maintain accurate mental models of a wide range of colleagues, ensuring their technical and architectural decisions elevate the team’s capabilities rather than imposing unnecessary friction.
Member of Technical Staff
Each of us:
Craft & Delivery
- Grasps computation and systems fundamentals at an undergraduate or better level
- Ships deliverables that consistently meet leadership’s standards
Culture & Communication
- Takes responsibility for their relationship with every person they interact with professionally
- Upholds our core values, embraces team culture, and champions team choices—even those they previously argued against
- Acts sometimes as a teacher, sometimes as a student: Apprentices are occasionally invited to teach what they know, and leaders are expected to demonstrate curiosity towards, gratitude when corrected by, and willingness to learn from those they outrank — modeling the humility towards reality we value
- Communicates with clarity and precision, in writing and speech
Autonomy & Ownership
- Exhibits general “knowledge professional” skills (time management, email triage, spreadsheet use, domain vocabulary, etc.)
- Learns independently, embraces adjacent technical skills when an assignment calls for them, and exercises excellent judgment on when to ask for help
- Owns any urgent problem they notice until it is fixed or explicitly claimed by a colleague
- Can make technical sense of complex, unfamiliar phenomena
Before specifying the expectations specific to each rank, we will describe the defining skill of software engineering.
Making Technical Sense
Developers routinely face bewildering mysteries. Competent developers know how to track down the clues that will convert an enigma first into an effective mental model, and then into a solved problem. This skill — making technical sense — is a primary differentiator of engineering levels.
Confronted with the mysterious timeout of a REST request:
- An Apprentice gets stuck and asks for help
- A Core developer drops into a debugger, notices that the underlying HTTP library is complaining about self-signed certificates, and identifies a workaround with 15 minutes of Googling
- A Senior developer updates the request code to make the error and its fix explicit. They then create a ticket to rework how SSL certificates are managed in the development environment
- A Staff developer observes their colleague’s activity, recognizes that the issue is one more drawback of the system’s microservice architecture, and slightly adjusts their calculation of the cost/benefit ratio of replacing it
The Apprentice incurs a small, worthy investment cost for a teammate. The Core developer solves the problem in front of them. The Senior developer addresses the class of problem. The Staff developer silently stalks much bigger game.
Apprentice
An Apprentice:
-
Has basic competence in our development environment and working practices
-
Has learned a subset of our code base
-
Can deliver incremental improvements within that subset, though they will still experience routine blockers
-
Is not expected to notice when an assignment should be redefined
-
Is learning to make technical sense of unfamiliar contexts
-
Owns their general professionalism, but is not yet expected to own their half of team relationships
-
May not produce value equivalent to their compensation in their first months on the team
-
Is steadily developing towards Core:
- Embraces stretch assignments
- Treats mistakes as productive experiments
- Owns their productivity, but eagerly accepts coaching
Promotion to Core
An Apprentice is expected to earn promotion to Core by:
- Delivering value across much of the code base
- Establishing peer relationships across their feature delivery team, and a few outside it
- Owning and steadily increasing their productivity, relying progressively less on guidance
- Participating in the day-to-day structuring of work
When an Apprentice is not on track for earning promotion at the two-year mark, their manager should diagnose whether they need better support or a different career path.
Core Developer
A Core developer is a versatile, productive practitioner of their craft who:
- Delivers high-quality new work steadily and efficiently
- Handles competing demands reliably, treating peer review as a first-class obligation
- Collaborates competently with their immediate managers and peers, owning their half of each relationship
In their area of expertise, Core developers can:
- Investigate feature-sized problems
- Design straightforward solutions to those problems
- Assist with decomposing features into epics and tickets
- Make technical sense of unfamiliar code and systems
- Maintain familiarity with the bulk of the code base, occasionally serving as the de facto team expert on a subset
- Partner with a leader to represent the team to external stakeholders
Core developers own their productivity by:
- Proactively shaping their assignments to maximize the value they deliver
- Routinely getting themselves unstuck
Consider how a Core developer shapes work. The team owns a database of installed battery energy storage systems, with a table representing individual batteries by customer, location, power output, and energy capacity. A previous sprint added a JSON packet column to capture static product attributes: manufacturer, model, and serial number. A Product Manager proposes extending that packet with an efficiency field and frames it as a single small ticket.
A Core developer recognizes several problems with this approach. Efficiency is an observed and dynamic value, not a static product attribute: it doesn’t belong in a packet alongside manufacturer and model. The developer confirms that queries will take the form of “which makes and models perform best?”, which means the existing packet should also be decomposed into columns rather than left as JSON. The restructuring of existing records requires a migration. The developer schedules a short call to walk the P.M. through their conclusion: what looked like a half-day extension is actually a three-ticket work stream covering schema design, backend changes, and data migration.
Promotion to Senior
A Core developer earns promotion to Senior by:
-
Maintaining high productivity on their assigned work
-
Becoming a productivity multiplier for those around them in any of several ways:
- Serving as an organizational resource (mentor, technical expert, external liaison, etc.)
- Increasing the signal-to-noise ratio of conversations in which they participate
- Reducing the entropy (“technical debt”) of the code base
-
Transforming tricky problems into durable solutions
Core developers typically spend 2–5 years growing to the Senior level. The majority, given proper support, will achieve this milestone.
The heart of an Engineering Manager’s job is to grow Core developers into Senior developers.
Senior Developer
Senior developers are more effective than Core developers across multiple dimensions. They:
-
Deliver work that delights Product Managers and the customers they represent, while simultaneously increasing the quality of the code base, even when given broadly defined tasks
-
Demonstrate mastery of their craft, notably in the review of peers’ work
-
Participate effectively in the team’s technical decisions:
- Sometimes by introducing the eventual solution and setting a new direction
- Sometimes by leading as a technical communicator
- Often by partnering with technical leads and Product Managers on work definition and estimation
- Often by minimizing the tradeoffs among feature scope, shipping velocity, and code base quality
- Always by listening well and being ready to defer to others’ perspectives
-
Model technical excellence and professional camaraderie — a manager guiding a Core or Apprentice developer can often point to a Senior colleague and say: “act like them”
-
Generate significantly more business value than the already high baseline of a median Core developer
Senior developers typically thrive in one of two modes:
- Delivering exceptional individual output while providing moderate support to others
- Delivering solid individual output while acting as a productivity multiplier for others
Consider how a Senior developer finds more value in a routine assignment than was asked for. The team owns an IoT control system whose backend is riddled with duplicate logic for legacy and current protocols. The two versions aren’t semantically equivalent: IoT devices using the legacy protocol can send messages that can’t be translated to the current protocol. A Senior developer starts work on a bug in the legacy logic, and notices an adjacent block of tricky code that they suspect is no longer being invoked. They search recent logs and confirm that intuition. They then realize that the subset of the legacy protocol which is actually being used maps almost perfectly to the new protocol — the legacy devices could send untranslatable messages, but in practice they never do. After shipping the bug fix they’ve been asked for, they quickly code a proof-of-concept translator from the old protocol to the new protocol that can be run at the edge. It works. They then write up an architectural decision record (ADR) showing how adding that translator at the edge will enable considerable simplification of the backend. Two sprints later, one of their teammates takes the proof-of-concept translator to production.
Staff Developer
The primary contribution of a Staff developer is to bring new technical capabilities to the team, ensuring their adoption in the code base and in their colleagues’ skill sets. Senior developers sometimes deliver features and sometimes improve systems; Staff developers often do both simultaneously. They:
-
Identify and seize opportunities to introduce needed technical capabilities
-
Convert risky mysteries into solid, implementable designs, effortlessly making technical sense of what they encounter:
- Act as excellent technical writers, regularly drafting clear and authoritative architectural decision records
- Design with a “mentor-first” approach, breaking work into rewarding growth assignments for delivery by less experienced colleagues and the crucial advances, which they complete efficiently
-
Frequently deliver value that significantly exceeds the initial request, impacting the business’s bottom line
-
Accomplish the above by doing different work, not more work
When the team hires a Senior developer, its ability to deliver value scales linearly. When it hires a Staff developer, it gains new technical capabilities that produce compounding returns over time.
Consider a famous example of Staff-level work: Haiping Zhao’s escape from a tri-lemma confronting Facebook.
- Our large code base is in PHP
- PHP is an order of magnitude too resource-greedy for our emergent needs
- We cannot afford the opportunity cost of rewriting in a more efficient language
Zhao wrote a PHP-to-C++ transpiler which allowed the team to continue to enjoy the advantages of PHP while sharply reducing the deployed system’s resource costs.
Promotion to Staff
Promotion to Staff is slow — when it happens at all. The primary skill of a Staff developer is to convert ignorance, uncertainty, and risk into delivered solutions while increasing the team’s abilities. Where a Senior developer solves a difficult problem posed by other leaders, a Staff developer reframes the problem and guides a much more valuable solution into production.
Because it is their job to question and improve even good collaborative work, Staff developers must:
- See farther technically than their colleagues toward a better vision of what is possible
- Champion that vision to win over colleagues (including those in distant parts of the organization) so it is fully embraced
- Mentor those colleagues in the skills needed to realize the vision
Executing any one of those tasks is difficult. A Staff developer who does not perform all three has fallen short.
Every Senior developer is a cherished member of the team. Even so, many will struggle to reach Staff. Growing a Staff developer requires Staff-level technical vision, which many Engineering Managers cannot model directly. Every Engineering Manager can, however, cultivate a fertile environment in which Staff abilities can sprout and flower, by feeding Senior developers a steady diet of technical conundrums to wrestle with:
- What is known in the industry about this challenge? Has it been solved? Has a comparable challenge been solved?
- Are there similar problems whose solutions promise to produce more value or incur lower costs? E.g., while solving the whole problem will take 3 team-months, might solving 80% of the problem take only 1 developer-month — an order-of-magnitude opportunity cost reduction?
- Is there a promising investigation they can perform quickly?
- Can they write up their findings as a crisp, defensible verdict? Do they identify valuable opportunities with some frequency?
The key evidence is ADRs whose recommendations go into production. Senior developers whose creative, high-upside work repeatedly moves the organization forward are candidates for promotion to Staff.
Humility Towards Reality
Software developers are rewarded for making technical sense. Many have been labelled precociously intelligent since childhood. Because identities are persistent and projecting confidence is often rewarded, there is a steady pull in technical organizations towards brash self-assurance. It is every developer’s responsibility to cultivate humility towards reality.
- Apprentices must demonstrate “beginner’s mind”: humility towards the skills of their craft.
- Core developers live in the parable of the blind men and the elephant. They often wrestle with tasks bigger than any one person grasps. They must turn conflicts latent in that diversity of perspective into shared understanding richer than individual attention windows. They need humility towards the intricate complexity of their assignments.
- Senior developers use task assignments, the smallest unit of work, as levers to move the surrounding code base forward. They need humility towards the expanse of the organization’s infrastructure.
- Staff developers see further and more widely than their peers. They start where typical Senior concerns end, by considering the organization’s systems and asking not what they are but what they should be. To stretch beyond the compromises of the current code base, they need humility towards the best work done in industry.
- All of those roles are anchored in established technology. Once in a great while, a developer looks past current technology to ask whether they can build software that reaches new parts of external reality. People who stretch beyond where anyone has previously reached show humility towards the world.
Principal Developer
Principal developers are rare birds. Only a small minority of engineering organizations have roosts which suit them. They are roughly equivalent to tenured professors at research institutions:
- Their job is to produce novel work of great value, an inherently uncontrollable endeavor
- They are players with their own agenda rather than reports expected to conform to a standard role
- When they succeed, the result will often become a public good, open sourced to serve as a Schelling point and as evidence of the developer’s achievement: R, rsync, Ruby, Redis, Rust, the Raft algorithm, React …
Principal is a role before it is a rank. Assigning someone to Principal work is like participating in a startup’s seed round: they might burn through your investment with little to show for it, they might do exactly what they hoped, or their work might evolve in a surprising direction. Key issues to work out during the assignment process include:
- How does the Principal’s technical vision overlap with the organization’s business ambitions?
- On what cadence does the Principal report activity, progress, and results?
- Should the position be structured, formally or informally, as a contract? Should the bounds be set by time or milestone?
- To what extent does the organization value successful experiments with negative results (establishing that possible value can’t be realized)?
- If the Principal needs additional resources, what is the process for weighing their request?
Day to day, the Principal:
- Writes code that tests ambitious hypotheses
- Converts the resulting existence proofs into practical libraries
- Races to explore the frontier of knowledge, which often looks like staring at the ceiling lost in thought
- Gets along well with their teammates, but doesn’t nurture the existing relationship mesh the way a Staff developer would — if the Principal’s work succeeds, it will productively disrupt that mesh
A Path to Principal
Your code base grew explosively — from a hacked-together proof of concept that found product-market fit immediately, to a monolith that accepted technical debt as the price of rapid feature development, and now via a series of acquisitions that have added irreducible complexity. Quality, always shaky, is degrading, and velocity has stalled. The tangled integrations and mismatched components that make up the current system mean that acceptance tests are the only reliable way to catch issues. Unfortunately, the same problems that you want to catch with acceptance tests make them unusably slow and resource-intensive. You’re stuck.
A Staff developer devises an extension of visual regression testing to application data state. One of their new tests effectively replaces 5-15 existing tests, runs quicker than any of them, and catches many more regressions. It looks like you can remove the staging tier from your release infrastructure. As the organization adopts this huge win, the Staff developer drops a second bombshell: the state snapshot developed for testing, modified and extended, can serve as a compact representation of the entire system.
You have never seen anything quite like it.
The implications—for quality, velocity, even product—race through your mind. It’s time to assemble a team to realize this breakthrough. The Staff — soon to be Principal — developer will need teammates who won’t be daunted by the creative-destruction aspects of the new approach. Yet even as they are slicing through load-bearing compromises in the existing system, they have to keep it working and serving customers. It will be a fine balance, but the developer’s demo earned cheers across the engineering organization. You’re going to disappoint engineers who don’t get picked for the new team. Product participation will be a trickier edge to dance along. The technical approach is new and fragile. A strong competing perspective could disrupt it before it has grown roots. You decide to operate the team without Product for the first quarter, then review.
Engineering leaders must begin with humility towards the reality of the business they serve and the people they lead. The last organization I built didn’t map exactly to this idealized ladder and neither should yours. But it should be built on the same capabilities: owning relationships, making technical sense, and humility towards reality. Management is the craft of weaving clean principles and messy facts into a coherent whole.