Skip to content

Perfection Is Irrational

Quality is not a binary. It is a continuous variable with a steep, often exponential, cost curve. The question "is this perfect?" is almost never the right question. The right question is "is this the right level of quality for what this software is being asked to do?"

Most overspend on software comes from confusing those two questions. So does most underspend. The first mistake builds a Mars rover when the team needed an internal dashboard. The second mistake builds an internal dashboard when the team needed a Mars rover.

The Cost of Each Additional Nine

In operational systems, reliability is often measured in "nines" of uptime: 99% (two nines), 99.9% (three nines), 99.99% (four nines), and so on. The cost of each additional nine is not linear. It is closer to exponential.1

  • Two nines means the system can be down for about three and a half days per year. Most teams reach this with conventional engineering.
  • Three nines means about eight hours of downtime per year. Achieving it usually requires deliberate redundancy, monitoring, and on-call processes.
  • Four nines means about an hour of downtime per year. The work required to maintain this is qualitatively different: load shedding, regional failover, chaos engineering practices, dedicated reliability roles.
  • Five nines and above means seconds-to-minutes of downtime per year. Almost no software outside life-critical, financial-clearing, or telecommunications systems actually requires this level, and very few teams can sustain it.

The same curve shows up in quality dimensions that are not about uptime: handling every edge case, supporting every browser, internationalizing every screen, surviving every adversarial input. Each marginal increase costs more than the one before it.

What "Appropriate Quality" Means

The right level of quality is the level that matches what the software is actually being asked to do. That depends on:

  • Consequence of failure. A failed transaction in a payments system has very different stakes from a failed render in an internal reporting tool. Quality investment should scale with what failure actually costs.
  • Audience and visibility. Software that customers see needs a different polish floor than software only the engineering team sees. Software regulators audit needs a different evidence trail than software that does not have to defend itself.
  • Reversibility. Decisions that can be undone cheaply do not need to be made perfectly the first time. Decisions that cannot be undone deserve more investment up front.
  • Lifetime. Code that will be live for five years justifies more investment than code that will be discarded after a single quarter's experiment.
  • Replaceability. A component that could be swapped out trivially carries less long-term risk than one that becomes load-bearing.

A team that applies the same quality bar to every piece of software is overspending somewhere and underspending somewhere else, almost by definition.2

Two Failure Modes, Equally Expensive

The reflex in many engineering cultures is to treat "more quality" as automatically good. It is not. There are two opposite failure modes, and the costs of each are large enough that taking either side as a default is wrong.

  • Underengineering ships software that breaks under conditions the team should have anticipated. The cost shows up as outages, support load, lost customers, security incidents, and emergency rebuilds. Underengineering is easy to recognize after the fact because the damage is visible.
  • Overengineering ships software that is hardened against conditions that will never occur, abstracted for flexibility that will never be needed, and instrumented for scale the team will never reach. The cost shows up as months of unrecouped engineering time, slow iteration on the things that do matter, and a codebase that is harder to change because everyone has to navigate the unused machinery. Overengineering is harder to recognize because the damage is invisible: it is the work that never happened because the team was busy gold-plating something else.

Both are forms of mis-spend. Both reflect a failure to ask what level of quality the situation actually warranted.

What This Looks Like in Practice

A few habits make this real rather than aspirational:

  • Set explicit reliability targets per system. Not all systems need the same uptime, response time, or error budget. Making the target explicit forces the team to ask whether they are over- or under-investing in any given area.1
  • Distinguish "good enough" from "best possible." Both have a place. Most internal tools and short-lived experiments need the first. Treating everything as if it needs the second is how teams burn out and ship slowly.
  • Treat quality as a resource allocation problem. Engineering time spent on robustness in one place is time not spent on robustness elsewhere. Spending it well requires knowing where failure is actually expensive.
  • Be honest about the cost of the next nine. When someone proposes raising the quality bar, ask what it will cost and what failure it is preventing. If neither answer is concrete, the proposal is decoration, not engineering.
  • Revisit targets as stakes change. A tool that started as a throwaway experiment can quietly become load-bearing. When that happens, the original quality target is no longer the right one, and the team needs to know.

Key principle

Overengineering can waste money just as surely as underengineering can create risk. The responsible question is never "can this be perfect?" but "what level of reliability, usability, and operational risk is appropriate for what this software is being asked to do?"

See also: Software Is Economics, Total Cost of Ownership, Quality Is Designed In, Testing Is Not Quality, Maintainability.



  1. Betsy Beyer, Chris Jones, Jennifer Petoff, and Niall Richard Murphy (eds.), Site Reliability Engineering: How Google Runs Production Systems (O'Reilly, 2016). The canonical articulation of the "error budget" concept and the argument that 100% is almost always the wrong reliability target. Available online: https://sre.google/sre-book/ 

  2. Joel Spolsky, Five Worlds (2002). Argues that software differs not by quality but by category: a packaged shrinkwrap product, an internal tool, an embedded system, a game, and a throwaway script have fundamentally different definitions of "done," and applying any one definition to another category produces predictable failure.