As a metaphor and practice, technical debt is holding us back

Ward Cunningham’s concept of technical debt should forever be held in high esteem. His easy-to-understand metaphor unlocked meaningful discussions on the risks and impact of technical trade-offs in software development. It enabled the expression of ideas and concerns many technologists had previously struggled to convey. Its positive impacts over time cannot be understated. However, the now overloaded notion of technical debt is hampering the evolution of software development practices. Counterintuitively, technical debt is limiting the ability to understand and prioritize technical work, ultimately limiting value creation.

Metaphorical origins

When I began my career 25 years ago, building a house was the predominant metaphor used to understand key aspects of software development. In this analogy, stakeholders acted as the future tenants, specifying what needed to be built and at what cost. Programmers played the role of plumbers, carpenters, electricians, and other tradespeople building the house. Tension inevitably erupted after the initial phase of construction. Stakeholders would be surprised and upset, perceiving the house as a money pit:

  • A new addition requires changes to the existing housing infrastructure. Why is rework necessary for a net new room?
  • More tenants using the house causes the floors to collapse. Why can’t it handle a few more people inside it?
  • After a few years and many changes to the house, a seemingly simple task like hanging a picture in the living room causes the furnace to break down.[1] Why does every change inexplicably cause unforeseen trouble?

When applied to software development, the construction metaphor has many flaws. Its biggest one is creating an expectation that once software (the house) is built, it can easily be extended, and maintenance is minimal and predictable.

In contrast to the construction analogy, Cunningham’s technical debt metaphor is nearly perfect in its illustration of this core challenge of software development:

  • Deferring technical work is like borrowing money.
  • Refactoring is like repaying the principal.
  • Slower development due to complexity is like paying interest.
  • The whole project caving under a mess is like when the big guys come around and slam your hands in the car door for not paying up. [2]

This straightforward framing unlocked a broader understanding of the cost of tradeoffs and the need for maintenance when building software over an extended period. Non-technical stakeholders and engineers benefited alike. As I moved from senior engineer to tech lead to architect, technical debt helped me articulate why investment in technical work is critical. Technical debt was the topic of my first conference talk; I was so excited to spread the word!

Incremental expansion

As revelatory as it was, the initial definition of technical debt was imperfect; it didn’t account for unintentionally deferred work (caused by bad design, ignorance, etc.). Martin Fowler addressed this by expanding the definition and providing a mental model of reckless vs. prudent and deliberate vs. inadvertent technical debt. [3] Fowler’s extension of technical debt offers helpful nuance and strengthens the underlying metaphor. The same challenge of when and how to pay down the debt applies regardless of the cause.

Explosion of coverage

Not all expansion of a good idea is a good thing. A broadening of what technical debt covers occurred as awareness and understanding of it increased. Unfortunately, this accumulating scope muddied the metaphorical waters. One example of this inflation is an academic paper published in 2014 that identified 13 types of technical debt:

  • Architecture debt
  • Build debt
  • Code debt
  • Defect debt
  • Design debt
  • Documentation debt
  • Infrastructure debt
  • People debt
  • Process debt
  • Requirement debt
  • Service debt
  • Test automation debt
  • Test debt

It’s easy to assume the good intentions behind this ontology. For example, infrastructure and automated tests are excellent examples of areas beyond core application code where the line between “good enough” and “too much” is highly subjective and debatable. Applying the lens of debt to these areas makes sense so they can be revisited and potentially improved later. However, debt categories such as “defect,” “people,” and “requirement” are all areas with typically well-established means to assess, track, and act upon them. What benefit is gained from framing them as technical debt? This overzealous application of technical debt opens the door to additional difficulties.

Organization as avoidance

Once an expansive definition of technical debt is established, a natural next step is to break down and organize what it encompasses. After all, a common principle in software development is to decompose the big problems. All the categories need to be clarified, all the instances accounted for, all the relationships between potential work identified, etc. This can certainly be helpful, but only to a degree. Classifying and quantifying technical debt can provide rough indicators of underserved areas of a tech stack or a need to recalibrate acceptable trade-offs during development. However, efforts to inventory technical debt can quickly become distractions and encourage busy work. As a result, engineering organizations become like my grandfather, a carpenter and a child of the Great Depression. He saved every screw, nail, piece of scrap wood, and old tool he came across in his work. Organizing all his odds and ends became a second job, yet little of what he saved was ever used. Likewise, I’ve seen too much effort spent configuring (and reconfiguring) Jira (or whatever ticket system you use) to categorize, quantify, and track technical debt “just right.” Individuals and teams mistake cataloging and sorting technical debt for acting on technical work.

Categorical infighting

Going further, expansively categorized technical debt creates motivation to use categories as a primary driver for prioritization decisions. Again, at a high level, classifying and quantifying technical debt can guide granular decisions on where improvements can be made. Individuals and teams can be encouraged to lean in a particular direction when navigating scope compromises. However, at a ticket-by-ticket or even project-by-project level, one type of debt will never be fundamentally more valuable than another. For example, security changes may or may not be more important than architecture updates. The details and larger context are critical to weighing the value of different types of work against each other. Decisions driven by categorization will fail to ensure the right work is done at the right time. When so much time and effort is invested in a complex framework to manage technical debt, limiting its influence on prioritization is challenging.

Bottom of the slippery slope

Further refinement and expansion of the technical debt metaphor have snowballed to a point where it is all-inclusive. I’ve seen and heard firsthand the following referred to as “technical debt”:

  • Foundational work required to implement a feature
  • All “non-feature” work

It might be tempting to assume the people who over-extend the idea come from outside the engineering discipline, such as product managers or high-level executives. However, software engineers have been just as culpable, if not more so. Humans crave mental shortcuts, and perceiving all debt as a whole rather than a long and ever-growing list of flavors is understandable. In the ticketing system, most people won’t register the type of debt indicated by a drop-down. They will simply notice that the ticket represents debt. Paradoxically, focusing so much on decomposing technical debt incentivizes many people see it as an opaque monolith.

No fun

When most, if not all, technical work is defined as debt, an aspect of the original metaphor becomes harmful: debt is perceived as a burdensome obligation. It represents something that could or should be put off for a long time, if not forever. Framing all technical work as debt defaults to it being a secondary concern to anything viewed as an investment, like features. Technical work is assumed to be a bottom-line obligation rather than a top-line accelerator. Classifying a large segment of potential work as debt diminishes its perceived value, especially when comparing it to “non-debt” work.

Mind the gap

Together, these problems with technical debt deepen the fundamental gap between the disciplines of engineering and product. Software development has long been divided into technical and non-technical (or “feature”) work. Separate processes are created for different roles to identify, track, and prioritize different types of work. For example, a typical pattern is the product manager stewarding “feature” work in cross-functional teams, with the engineering manager handling “technical” work. Managing technical debt has become an engineering practice when the ultimate goal should be inclusive cross-discipline prioritization.

Don’t call the language police

To address the counterproductive application of technical debt, one might be tempted to wrangle its definition closer to its original form. Given the high risk of coming across as pedantic, I hesitate to suggest this. “Well, actually, technical debt means something else…” Modifying language won’t reverse the inflated notion of technical debt that has taken hold, nor will it improve our debt management processes. More importantly, reigning in the concept of technical debt does not result in a net improvement in the gap between product and engineering gap.

Focus on value

Moving beyond technical debt means focusing on the inherent value of technical work. As much as possible, technical work should be evaluated based on clear goals, success measurements, and solid reasoning. Assessing technical priorities against non-technical priorities should be a direct, “apples-to-apples” exercise. Although this may seem simple, I’ve seen technical practitioners struggle to explain the value of work. I attribute this to a lack of history with doing so. For too long, we’re relied on the concept of technical debt to express value for us. Focusing on technical value requires technical practitioners to level up and for the organization to break down barriers between disciplines.

The emergence of technical debt was initially a boon for software development. Unfortunately, it is now getting in the way of the difficult but necessary challenge of understanding and prioritizing technical work against other potential work. The metaphor of technical debt deserves its exalted place in history. It’s also time to move beyond it.


  1. I’m borrowing this analogy from Dean Hager, former CEO of Jamf. He leveraged it when explaining the company’s strategy of investing more in quality after years of focusing on top-line growth. It seemed to work well across a diverse audience. The more metaphors, the merrier! ↩︎

  2. I’m taking a few liberties with the original metaphor. (1) What many of us refer to as “technical debt” was initially framed as “complexity debt” by Cunningham. I’m using “technical debt” for simplicity. (2) I modified the language of the complexity debt metaphor. Again, I did this for simplicity. ↩︎

  3. https://martinfowler.com/bliki/TechnicalDebtQuadrant.html ↩︎


Feedback is welcome via Bluesky: @computersandpeople.com.