← all posts

The Most Expensive Bugs Never Reach Production

A runtime bug is loud. It breaks, you find it, you fix it. A decision bug is silent. It works perfectly while it quietly makes everything downstream more expensive. You don't debug those. You inherit them.

The most expensive bugs never reach production.

Because they aren't runtime bugs. They're decisions.

We've built an entire discipline around catching the cheap bugs. Linters, tests, type checkers, code review, observability, alerting. All of it aimed at the bug that throws, the bug that breaks, the bug that shows up on a graph. And all of it is blind to the bugs that actually sink projects, because those bugs never run.

The bugs that bankrupt projects don't throw

The failures that kill a project don't announce themselves the way a runtime bug does. There's no stack trace. Nobody gets paged. No alert fires, because from the machine's point of view, nothing is wrong at all. The code does exactly what it was told.

They look like this:

  • the wrong database
  • the wrong ownership model
  • the wrong service boundaries
  • the wrong product assumption
  • the wrong operational model

Nobody files a Jira ticket for "we picked the wrong database." There's no row in the bug tracker for "this service owns data it shouldn't." These aren't defects in the code. They're defects in the decision the code faithfully implements, and our entire toolchain is designed to verify the code, not the decision.

A decision bug is a sentence nobody pushed back on

Here's the uncomfortable part. Each of these bugs was, at some point, a single sentence in a meeting that nobody challenged.

The wrong boundary is a sentence in a design review that nobody pushed back on. It costs more than every syntax error your team will ever write, combined.

"Let's just put it in the same database for now." "This team can own that too, it's basically the same thing." "We can make that call synchronous, it'll be fine." Each one sounds reasonable in the room. Each one is cheap to say and nearly free to agree to. And each one quietly sets a price that the project pays for years, in migrations that can't happen cleanly, in teams that can't move independently, in an operational model that fights you every day.

That's the cruel economics of it. The most expensive bugs are the cheapest ones to introduce. They cost one unchallenged sentence to create and a quarter of engineering to undo.

Loud bugs versus silent bugs

The reason we under-invest in catching these is that our instincts are tuned to loud bugs, and decision bugs are silent.

A runtime bug is loud. It breaks, you find it, you fix it. The feedback loop is tight and satisfying: the test goes red, you make it green, you ship. The whole system is optimized to surface this kind of failure as fast as possible.

A decision bug is silent. It works perfectly. It passes every test, clears every review, runs flawlessly in production, and the entire time it's making everything downstream more expensive. The wrong boundary doesn't crash. It just means every feature for the next two years costs 20% more than it should, because everything has to route around the seam you put in the wrong place. You never see the bill itemized. You just feel the whole project getting heavier.

You don't debug those.

You inherit them.

Why these are getting more common, not less

You'd hope that better tooling would help here. It doesn't, and AI is making the imbalance sharper, not softer. When buildability gets cheap, the implementation stops being the risk. The machine will hand you a clean, well-tested, beautifully organized implementation of whatever you asked for, including the wrong thing.

So the relative weight of the decision goes up. A perfect implementation of the wrong database is arguably worse than a sloppy one, because the polish makes the wrongness harder to question. Everything looks healthy. The tests pass. The review approved. The only thing wrong with it is the part no test was ever going to check. This is the same shift behind the review moving up the stack: when the code is clean by default, the surviving bugs are all decisions.

Catching the bugs that don't run

If the most expensive bugs are decisions, then the most valuable review is the one that happens before there's any code to review. That's an awkward thing to operationalize, because there's no diff to comment on and no test to write. But it's catchable, if you decide to look:

  • Interrogate the boundary before you build inside it. Is this seam where it belongs, or where it was convenient? Architecture review beats code review precisely because this is the bug it's hunting.
  • Name the owner out loud, early. The wrong ownership model is an organizational decision masquerading as a technical one, and unclear ownership is how reliability problems are born.
  • Test the product assumption before the code. The cheapest place to discover you're building the wrong thing is a conversation, not a launch.
  • Pick the operational model deliberately. How this runs at 3am is a decision you're making whether you think about it or not, so think about it.

None of these produce a green checkmark. All of them prevent the bugs that cost the most, precisely because those bugs were never going to show up where your tools are looking.

The one-line version

The bugs that bankrupt projects don't throw a stack trace. They're decisions, made in a sentence nobody challenged, and they cost more than every syntax error combined. You don't debug those. You inherit them.