← All posts

The Engineering Ladder Trap: Why Promotion-Chasing Hurts Your Growth

The Engineering Ladder Trap: Why Promotion-Chasing Hurts Your Growth

I've watched dozens of talented engineers stall their careers by obsessing over promotion criteria. They chase visibility wins, accumulate Jira tickets like Pokemon cards, and optimize every decision around "will this look good in my performance review?" Meanwhile, the engineers who actually get promoted—and stay happy—are playing a completely different game. After 12 years and four promotions (plus one demotion that taught me more than any success), I've learned that the engineering ladder is both essential and deeply misleading.

The Metrics That Don't Matter (But Everyone Tracks)

Early in my career, I kept a spreadsheet of every PR, every bug fix, every feature I shipped. I thought volume mattered. I was wrong. The engineer next to me shipped half as many PRs but got promoted first. Why? Because while I was churning out features, she was fixing the right problems. She deleted more code than she wrote. She made the team faster, not just herself productive.

The promotion paradox: The behaviors that get you promoted to senior engineer are not the same behaviors that got you from junior to mid-level. Yet most engineers keep optimizing for individual output long after it stops mattering.

Here's what I stopped tracking: lines of code written, number of tickets closed, pull requests merged per sprint. Here's what I started tracking: number of production incidents caused by my team's code (and how that trend changed), how many engineers could confidently modify the systems I built, time-to-productivity for new team members in my codebase.

The Invisible Work That Actually Compounds

The best career advice I ever received was from a staff engineer who told me: "Your job is to make yourself obsolete." It sounded insane. But she was right. The work that compounds—that creates lasting value and gets you promoted—is the work that lives on after you stop touching it. Documentation that prevents questions. Abstractions that make the next feature trivial. Tooling that eliminates entire classes of bugs.

// This is promotion-worthy engineering:
// Not because it's complex, but because it prevents
// 50 future bugs and makes the next engineer's life easier

type Result<T, E = Error> = 
  | { ok: true; value: T }
  | { ok: false; error: E };

// Forces explicit error handling at compile time
async function fetchUser(id: string): Promise<Result<User>> {
  try {
    const user = await db.user.findUnique({ where: { id } });
    if (!user) {
      return { ok: false, error: new NotFoundError('User not found') };
    }
    return { ok: true, value: user };
  } catch (error) {
    return { ok: false, error: error as Error };
  }
}

// Now every caller must handle both cases
const result = await fetchUser('123');
if (result.ok) {
  console.log(result.value.email);
} else {
  logger.error('Failed to fetch user', result.error);
}

This pattern isn't clever for cleverness's sake. It encodes error handling into the type system, preventing an entire class of production bugs. Six months later, three junior engineers thanked me because TypeScript literally wouldn't let them forget to handle errors. That's leverage. That's the work that gets you promoted.

Build Leverage, Not Just Features

The transition from mid-level to senior is about leverage. From senior to staff is about organizational leverage. But most engineers never make this shift because they're addicted to the dopamine hit of shipping features. Features are visible. Features get praise in standups. But features are also linear—you ship one, then you ship another, then another. There's no compounding.

  • Linear work: Implementing feature requests, fixing bugs in isolation, attending meetings
  • Leverage work: Building frameworks that make features trivial, creating tooling that prevents bug classes, writing documentation that answers questions you'd otherwise answer 50 times
  • Organizational leverage: Changing team processes, mentoring engineers who then mentor others, making architectural decisions that guide dozens of future decisions

The hard truth: you need to do less feature work to get promoted. This feels backwards because feature work is what got you hired. But at some point, your impact needs to multiply beyond what you personally can type into an IDE. I've seen engineers stuck at senior for years because they're the best individual contributors on the team—so good that leadership can't imagine promoting them away from shipping features.

The Demotion That Taught Me Everything

Three years ago, I got demoted from staff back to senior during a reorg. It was devastating. It was also the best thing that happened to my career. Why? Because it forced me to confront an uncomfortable truth: I had been promoted for the wrong reasons. I was great at putting out fires, at heroic debugging sessions, at being the person everyone Slacked at 2am. I was rewarded for being indispensable. But I wasn't actually making the team better—I was making them dependent.

If you're the hero who saves the day, ask yourself: why does your team need saving so often? Real seniority is making heroics unnecessary.
// Before: I was the only person who understood this
function processPayment(user, amount, card) {
  // 200 lines of undocumented payment logic
  // with edge cases only I knew about
}

// After: I made myself obsolete
class PaymentProcessor {
  /**
   * Processes a payment with automatic retry and idempotency.
   * 
   * @throws {InsufficientFundsError} - User has insufficient balance
   * @throws {InvalidCardError} - Card failed validation
   * @throws {PaymentGatewayError} - External service unavailable
   * 
   * See docs/payments.md for architecture overview and runbook
   */
  async process(request: PaymentRequest): Promise<PaymentResult> {
    const validator = new PaymentValidator();
    const gateway = new StripeGateway(this.config);
    const idempotency = new IdempotencyGuard(this.redis);
    
    return await idempotency.guard(request.idempotencyKey, async () => {
      await validator.validate(request);
      return await gateway.charge(request);
    });
  }
}

The second version isn't just better code. It's a system that three other engineers can confidently modify, debug, and extend. It has documentation, clear error cases, and separation of concerns. It doesn't need a hero. That's the difference between senior and staff: staff engineers build systems that don't need them.

What to Optimize For Instead

Stop optimizing for your next promotion. Start optimizing for the engineer you want to be in five years. That person isn't defined by their title—they're defined by their judgment, their ability to navigate ambiguity, and the trail of capable engineers they've helped develop. Chase hard problems, not visibility. Build systems, not features. Make your team faster, not just yourself productive. The promotions will come, but more importantly, you'll actually deserve them.