After reading the previous chapter, it would be easy to jump to conclusions.

It would be easy to say:

  • Traditional organizations were slow.
  • Agile organizations didn’t do Agile properly.
  • If only teams were more disciplined, things would be better.

This chapter is written to stop that thinking.

Because before we talk about why things must change, we need to acknowledge something honestly:

The way most engineering organizations work today is not accidental.

It is the result of years—sometimes decades—of practical learning under very real constraints.

And for a long time, these models didn’t just exist. They worked.


Software Was Hard, Slow, and Expensive

For most of the history of software development, writing code was not cheap.

  • Writing correct code took time.
  • Understanding existing systems took even more time.
  • Debugging was painful.
  • Deploying was risky.
  • Infrastructure was scarce and expensive.
  • Production failures were career-limiting events.

In that world, speed was dangerous.

Moving fast didn’t mean learning faster. It meant breaking things in ways you didn’t understand yet.

So organizations learned—often the hard way—that they needed protection mechanisms.

That is where many of the structures we now criticize actually came from.


Humans Writing Code Were the Bottleneck

This is the most important idea in this chapter.

For a long time, human-written code was the primary bottleneck in software delivery.

Not business ideas.
Not infrastructure.
Not even coordination.

It was the fact that:

  • Only humans could translate intent into code.
  • Good engineers were rare.
  • Senior engineers were even rarer.
  • Knowledge lived in people’s heads.
  • Context transfer was slow and lossy.

When this is your reality, you optimize differently.

You don’t optimize for speed. You optimize for protecting scarce human expertise.


Specialization Was a Rational Survival Strategy

Specialization did not emerge because people loved silos.

It emerged because depth mattered more than breadth.

When systems are complex and opaque:

  • Knowing a small part very deeply is safer than knowing everything shallowly.
  • Context switching increases mistakes.
  • “Full ownership” becomes unrealistic.

So organizations naturally created roles:

  • Frontend engineers
  • Backend engineers
  • QA engineers
  • Infrastructure / DevOps engineers
  • Security engineers

Each role reduced risk by limiting cognitive load.

This wasn’t about efficiency. It was about survivability.


Handoffs Reduced Individual Risk

Today, handoffs are often criticized—and rightly so.

But historically, handoffs served an important function.

They distributed responsibility.

When something went wrong:

  • QA missed it.
  • Infrastructure misconfigured it.
  • Security didn’t flag it.
  • Product didn’t specify it clearly.

No single individual carried full blame.

This made large-scale delivery emotionally and organizationally survivable.

Organizations don’t just optimize for output. They also optimize for psychological safety—even if they don’t say it out loud.


QA as a Gate Made Sense

In a world where:

  • Engineers were specialized
  • Integration happened late
  • Feedback was slow

QA became the final line of defense.

Not because engineers didn’t care about quality, but because:

  • No single engineer saw the whole system.
  • No one trusted partial validation.
  • Production failures were costly.

So QA existed as a risk buffer.

Manual testing survived because automation couldn’t keep up with constant change.

This wasn’t incompetence. It was pragmatism.


Infrastructure and Security Had to Be Centralized

Infrastructure used to be:

  • Expensive
  • Fragile
  • Hard to automate
  • Easy to misconfigure

Security vulnerabilities were:

  • Hard to detect
  • Harder to reason about
  • Easy to exploit once exposed

Centralization wasn’t about control for its own sake.

It was about reducing blast radius.

Giving every team full control would have caused more harm than good.

So organizations centralized these functions—and accepted slower delivery as the trade-off.


Agile Improved the Flow, Not the Assumption

When Agile arrived, it did not replace this world overnight.

Agile didn’t say:

“Human-written code is no longer the bottleneck.”

It said:

“Let’s reduce waste and get feedback sooner.”

So Agile improved flow within the same constraint.

That’s why:

  • Story points mattered.
  • Velocity mattered.
  • Predictability mattered.
  • Sprints mattered.

Even in Agile organizations, the real definition of “done” was rarely “in production”.

Because production still depended on:

  • Integrations
  • Infrastructure
  • Security
  • Coordination across teams

So even Agile organizations shipped slower than they planned.

And that was normal.


Success Reinforced the Model

Perhaps the most important reason these models lasted is simple:

They worked well enough.

Companies:

  • Grew
  • Made money
  • Shipped products
  • Built careers

Entire industries were built on these models.

No organization abandons a model that keeps the lights on.

Success is the strongest argument for correctness.


What This Chapter Is Really Saying

This chapter is not saying:

  • Traditional organizations are bad.
  • Agile organizations failed.
  • People didn’t try hard enough.

It is saying something more uncomfortable—and more honest:

These models were optimized for a world where writing code was expensive, slow, and risky.

They were designed to be:

  • Safe
  • Scalable
  • Survivable

Not fast.


Why This Matters Now

If the assumptions that shaped these models were still true, there would be no reason to change anything.

But that assumption—the cost and speed of writing code—is no longer stable.

And when the primary bottleneck shifts, every optimization around it starts to misfire.

That is not a failure of people or process.

It is a signal.

And understanding why the old world worked is the only way to understand why it now feels strained.

The next chapter explores that strain—and the invisible cost we’ve been carrying without naming it.