When I was promoted to senior engineer, my manager said something that stuck with me: "We're not promoting you because you write better code. We're promoting you because you make better decisions about what code to write."
At the time, I thought it was a nice way of putting it. Five years later, I think it's the most important thing anyone has told me about this profession.
The technical skills gap between junior and senior engineers is real but narrowing. With modern tooling, documentation, and AI assistants, a motivated junior can write production-quality code faster than ever. What hasn't gotten easier — what no tool can automate — is the decision-making that determines whether you're writing the right code in the right way at the right time.
Here are the specific decision-making skills that I've observed separating senior engineers from everyone else, along with how I developed each one (usually the hard way).
Skill 1: Knowing When Not to Build
Junior engineers get excited about building. A problem appears, and the instinct is to solve it with code. New feature request? Start designing the data model. Performance issue? Start optimizing. Bug report? Start debugging.
Senior engineers pause. The first question isn't "how do I build this?" — it's "should this be built at all?"
I learned this skill the expensive way. Early in my career, I spent three weeks building an internal tool for managing deployment configurations. It was well-designed, well-tested, and completely unnecessary. A YAML file and a README would have served the same purpose at 1% of the cost. I built it because building things was what I did. Nobody had taught me that not building is often the better decision.
The decision framework I use now:
Before building anything, ask:
- What happens if we don't build this?
- Is there an existing tool/service that solves 80% of this problem?
- What's the maintenance cost of this code over two years?
- Who will maintain this after I've moved to another project?
If the answer to #1 is "nothing significant changes," the right decision is usually to not build it. This sounds obvious, but it goes against every instinct a new developer has.
Skill 2: Making Decisions With Incomplete Information
Juniors want complete information before deciding. They research exhaustively. They prototype multiple approaches. They seek consensus. They're trying to find the objectively correct answer.
Seniors recognize that in most real-world situations, complete information doesn't exist. Waiting for it is itself a decision — and often a bad one, because delay has costs that are easy to underestimate.
The skill isn't making decisions recklessly. It's calibrating how much information you need based on the stakes and reversibility of the decision.
Low stakes, easily reversible: Decide in minutes. Choose a variable naming convention, pick a color for the staging environment, select which story to work on first. Any reasonable choice is fine. The cost of deliberating exceeds the cost of choosing suboptimally.
Medium stakes, moderately reversible: Spend an hour or two. Library selection, API design for internal services, testing strategy for a feature. Gather enough information to eliminate clearly bad options, then pick from the remaining candidates. Don't optimize — satisfice.
High stakes, difficult to reverse: Spend a day or two, maximum. Database selection, core architecture patterns, third-party vendor commitments. Gather information, consult experts, sleep on it. But still decide within days, not weeks.
The common junior mistake is treating every decision like it's high stakes. This creates analysis paralysis on decisions that don't warrant it and leaves less cognitive energy for the decisions that do.
A mentor told me: "If you can't tell the difference between your top two options after a day of research, they're probably both fine. Pick one and move forward." I've found this to be true roughly 90% of the time.
Skill 3: Second-Order Thinking
First-order thinking asks: "What happens when we do this?"
Second-order thinking asks: "And then what happens after that?"
Juniors tend to stop at first order. "If we add caching, the page loads faster." Seniors think through the cascade. "If we add caching, the page loads faster. But now we have cache invalidation to manage. Cache invalidation bugs will be harder to diagnose than the original performance issue. We need monitoring for cache hit rates. The caching layer adds a dependency that can fail independently. And when it does fail, the system needs to degrade gracefully rather than crash."
This isn't pessimism. It's completeness. Every technical decision creates second and third-order effects, and the ability to reason about them before they happen is what prevents the "we'll deal with that later" problems that consume so much engineering time.
How to develop this skill:
Practice premortems. Before implementing any significant change, spend five minutes asking "What could go wrong?" and "What happens after that?" Follow the chain at least three steps.
Study incident postmortems. Every production incident is a story about second-order effects that someone didn't anticipate. Read your team's postmortems with the question: "At what point in the decision chain could someone have predicted this?"
Review your past decisions. Monthly. Did the second-order effects you anticipated actually materialize? Did effects you didn't anticipate show up? What would you have done differently?
Skill 4: Distinguishing Reversible From Irreversible Decisions
Jeff Bezos calls these Type 1 and Type 2 decisions. Type 1 decisions are one-way doors — hard or impossible to reverse. Type 2 decisions are two-way doors — easily reversible.
The skill isn't just categorizing decisions. It's recognizing that reversibility degrades over time. A decision that's easily reversible on day one can become practically irreversible after three months of code building on top of it, data accumulating in its format, and other teams integrating with its interface.
I fell into this trap with an API design decision. The response format I chose was "easily reversible" on the day I shipped it. Three months later, four internal services and two external partners were consuming that format. Changing it would require coordinated migration across multiple teams. The decision had become irreversible not because of technical constraints but because of social and organizational ones.
Senior-level reversibility assessment asks:
- How quickly will other code/systems build on top of this decision?
- How many people/teams will be affected if we change course?
- Is there a point after which reversal becomes impractical? When is that point?
- If I'm going to change my mind, when is the last reasonable moment to do so?
Skill 5: Communicating Decisions and Trade-offs
A junior engineer might make a solid technical decision but can't explain why. When challenged, they either capitulate (abandoning a good decision because they can't defend it) or dig in (defending a decision with emotional conviction rather than structured reasoning).
Senior engineers articulate trade-offs explicitly. They can explain not just what they chose but what they didn't choose and why. They present decisions as trade-offs between competing values rather than as obviously correct answers.
The format I use for communicating decisions:
"We chose [option A] over [option B] and [option C] because [specific reason]. The trade-off is [what we're giving up]. We'd reconsider if [specific condition changed]."
This structure does several things:
- Shows you considered alternatives (builds trust)
- Makes the reasoning transparent (enables others to challenge specific logic rather than the overall decision)
- Acknowledges trade-offs (demonstrates maturity)
- Sets conditions for revisiting (prevents decisions from becoming permanent by default)
Skill 6: Building and Using Decision Rules
Juniors approach each decision fresh. Seniors accumulate decision rules — pre-commitments that handle entire categories of decisions automatically.
Some of mine:
- "Don't add a new dependency unless it saves at least a week of development time."
- "If an optimization isn't backed by profiling data, don't do it."
- "If a meeting doesn't have an agenda, decline it."
- "If a PR is over 400 lines, ask for it to be split."
- "If I'm unsure about a high-stakes decision, I sleep on it. No exceptions."
Each rule represents a lesson learned. The dependency rule came after a week lost to a poorly maintained library. The optimization rule came after I spent two days optimizing code that wasn't a bottleneck. The PR rule came after reviewing a 1,200-line PR and missing a critical bug.
Rules are powerful because they remove decision fatigue. When a 500-line PR comes in, I don't evaluate whether this specific PR should be split. The rule decides for me. My cognitive resources are preserved for decisions that don't have rules yet.
The practice of collecting and maintaining decision rules has become central to how I operate. I've found KeepRule's principles collection helpful not just for managing my own rules but for seeing how experienced thinkers across domains — from investing to military strategy to engineering — have codified their hard-won decision-making lessons into reusable principles.
Skill 7: Knowing When to Decide Alone and When to Involve Others
Junior engineers either decide everything alone (and miss important perspectives) or escalate everything (and create bottlenecks).
Seniors calibrate involvement based on the decision:
Decide alone: When you have clear ownership, the stakes are low to medium, and you have sufficient context. Don't waste other people's time on decisions you're qualified to make.
Consult then decide: When the decision affects others, when it's outside your deepest expertise, or when the stakes are high. Get input, then make the call yourself. The key word is "consult" — you're gathering information, not seeking consensus.
Decide together: When the decision requires buy-in from multiple stakeholders to succeed, or when the organizational impact is significant. True collaborative decisions should be rare. If everything is decided by committee, nothing gets decided quickly.
Escalate: When the decision is above your authority, when you genuinely don't have enough context, or when two reasonable people disagree and the tiebreaker needs to come from someone with broader perspective.
The most common junior mistake is consensus-seeking for decisions that should be made individually. The most common mid-level mistake is making decisions individually that should involve consultation. Calibrating this correctly is one of the clearest markers of senior judgment.
How to Develop These Skills Deliberately
These aren't skills you develop by writing more code. They develop through reflection, feedback, and deliberate practice:
Start a decision journal. Document your significant decisions, your reasoning, and a review date. Review monthly. This is the single highest-leverage practice for developing decision-making skill.
Study your failures. Not just what went wrong, but what decision led to the failure and what information you had at the time. Was the decision bad, or was the outcome unlucky? There's a critical difference.
Find a decision mentor. Not a technical mentor — a decision mentor. Someone who makes consistently good calls under uncertainty. Watch how they think, not just what they decide.
Read outside software. The best decision-making insights come from fields like investing, military strategy, medicine, and behavioral psychology. Software engineering is not unique in requiring good decisions under uncertainty, but it is behind other fields in studying the skill formally.
Practice explaining your reasoning. For every significant decision, articulate the trade-offs to someone else. If you can't explain why you chose option A over option B in a way that makes the listener understand the trade-offs, your own understanding isn't deep enough.
The Uncomfortable Truth
The gap between junior and senior isn't closed by learning more technologies, writing more code, or getting more years of experience. Plenty of engineers have ten years of experience making the same decision mistakes on repeat.
The gap is closed by treating decision-making as a skill — one that can be studied, practiced, measured, and improved. Most engineers never do this. They improve their technical skills deliberately and leave their decision-making skills to develop accidentally.
The engineers who advance fastest are the ones who realize that the decisions surrounding the code matter more than the code itself.
What decision-making skill do you wish someone had taught you earlier in your career? And if you're a senior or staff engineer — what do you see junior engineers struggling with most when it comes to decisions?
Top comments (0)