Technical Debt Is Not What You Think It Is


You have walked into a codebase and immediately reached for the phrase “technical debt” like it was a diagnosis. The shortcuts, the copy-pasted functions, the config files with no comments, the three different ways to handle authentication. You see them all at once and label the whole thing a mess. It feels good to call it that, because it tells you exactly what is wrong: someone else didn’t care enough to do it right.

Ward Cunningham coined the term in 1992 as a neutral financial metaphor. His point was simple: borrowing against future work lets you ship something valuable today. Paying it back means choosing to refactor later instead of building new features. The banking analogy works perfectly until people start using it as an accusation. That is where things go sideways. “Technical debt” stopped being a description of a tradeoff and became a moral judgment. Now every engineer who inherits messy code has a ready-made way to blame the previous team, even when that team shipped the only thing keeping the business alive.

The truth is that every shippable product accumulates technical debt because shipping requires making decisions you cannot fully anticipate. When you are under pressure to deliver a prototype, choosing a quick solution over a clean one is often the right call. The debt becomes visible later when someone tries to extend what was built, and by then the original context has evaporated. This is not negligence. It is the natural consequence of building things in conditions of imperfect information. The teams that ship nothing have zero technical debt and also zero impact.

The best engineering organizations do not try to eliminate technical debt. They treat it like financial debt: visible, tracked, and managed strategically. They know which debts are low-interest (a function with no tests but a clear purpose) versus high-interest (authentication logic buried in four different modules). They allocate capacity for paying down the expensive stuff without pretending they can erase all of it at once. This is harder than declaring war on debt, because it requires admitting that some debt was the right decision at the time and still choosing to invest in cleanup.

The next time you inherit a codebase that makes you want to write “technical debt” across every line in red marker, try a different question: what tradeoff was being made here? The answer is rarely “they didn’t care.” It is usually “they cared about shipping something that mattered more at the time than getting this part perfect.” That does not excuse everything. Some teams really are negligent. But most of them were just making real decisions under real constraints, and the codebase you inherited is the receipt for those choices. The useful question is not whether there is debt. It is whether anyone is keeping score.