Technical debt is a tempting metaphor to describe engineering trade-offs, but it’s also deeply flawed, undermines solid engineering thinking, and is anti-agile.

Debt as Metaphor

The essence of technical debt is to get something done now, very quickly, by borrowing against the future, when some of that work will have to be undone. The logic relies on financial debt as metaphor. And, it’s true that when you take out a loan, you get something now (money) that you then pay back later.

Beyond that, though, the metaphor is pretty broken.

When you take on financial debt, you’re borrowing money so you can make an investment. You believe that the investment will generate more money, which you’ll use to pay back the debt. You might be wrong—​not every investment works out! But at least you’re working from a rational theory here; there’s a direct line from taking on debt to paying it back.

The financial system also separates the party that wants to borrow the money from the party that loans it out. You can’t just decide to borrow money; you have to convince a bank to loan it to you. They’ll ask about your investment. They’ll ask about other assets, too. They’ll create an informed judgment as to whether you’re likely to pay back that debt. It’s still not a guarantee that your investment will work out, but the scrutiny weeds out a lot of bad ideas.

That’s not how technical debt works. When you take on technical debt, you’re implementing something with less quality than your normal standard. The thing you’re borrowing isn’t quality—​it’s anti-quality. You’re borrowing awfulness. You’re borrowing awfulness, loading up your product with it, and shipping it to your users.

Why would you do that?

Later, you need to "pay back"—i.e., get rid of—that awfulness. To pay off a debt of awfulness, you need quality. That’s the essence of technical debt, right there: borrow a bunch of awfulness so you can use it now, and then pay it back later with increased quality.

How does your investment in an awful product now help produce quality later?

The truth is, it doesn’t—​that’s where the metaphor breaks down. Taking on technical debt is not like taking out a loan. It’s not an investment that pays positive returns. Taking on technical debt does nothing to help pay off that debt later. If anything, it tends to produce more awfulness.

It is true that taking on technical debt might create an opportunity for reducing awfulness later. That can happen if delaying your product will cause you to run out of money, or lose your job, or go out of business. If any of those things happen, no one is around to pay back that awfulness. It might be better to ship an awful product now than nothing at all. (Maybe.) But when you do that, all you’re doing is shipping an awful product. You’re not making an investment in future quality. You’re not really taking on debt; you’re just making a compromise.

Engineering is Compromise

There’s nothing wrong with compromise. Indeed, compromise is at the heart of engineering. No car gets infinite mileage and instantaneous acceleration and is absolutely safe. These things aren’t achievable individually or in combination. As engineers, we make trade-offs. One reason auto manufacturers make a variety of models is to offer different combinations of efficiency, performance, and safety. Different people prefer different trade-offs.

When you engineer a software product, you make compromises on, among other things, its quality. You make trade-offs on other attributes as well: performance, size, development cost, and so on. There’s nothing wrong with that. All engineering is compromise, and so is software engineering. As engineers, our goal is to find a good compromise. That can be hard to do; there are many variables to consider.

When we bring technical debt into our engineering discussions, it skews our sense of compromise. Instead of forcing us to find the "sweet spot" amongst all of those variables right now, it leads us to believe that we can make severe compromises now and get much better results later. We might have any number of variables in mind when we consider those trade-offs, although quality is almost always in play.

But this is a kind of two-part fantasy. First, because the compromise we’re making now isn’t going to make things better later, as discussed above. Second, because it makes it easy to believe that the future version—​the one we’ll build when we "pay off the debt"--will be really good. It will be the car that’s both fast and efficient and safe! That’s why discussions about technical debt tend to be framed as choosing between a "hack" and the "right solution."

But look, there’s no right solution in engineering. It’s all compromise. Even if you do get to ship another version of your product, you aren’t going to find that constraints and trade-offs have been magically removed. If you try to build that "right solution," you will still run into trouble. You’ll still need to compromise.

Indeed, an engineer’s real job is to find a good compromise amongst relevant variables. And the one thing we should know with certainty is that solving the problem twice—​first the "hack", then "right"--can’t possibly be a better compromise than solving it once, because the aggregate cost of solving it twice is inevitably more. If you find yourself staring at this trade-off, then both of your options are wrong. Look for something in the middle. Look for a trade-off that will work the first time. Find a good compromise. That’s your job.

Anti-Agile

When you take on technical debt, you’re adding awfulness to your product. If you want to take that back out, you’ll need to spend time and energy doing that. Thus, when you’re taking on technical debt, you’re committing the organization’s future resources.

That might be acceptable if you have a crystal ball and it can confirm that restoring quality to your product will indeed be the organization’s top priority at that time. The two problems with this are (1) crystal balls don’t exist and (2) there’s always other important things to do.

Once you’ve shipped your product, you’ll have more to do—​not less! Customers might buy your product—​but clamor for new features. Customers might not buy your product—​due to lack of features. A competitor might introduce a new capability—​to which you have to respond. A new technology that you want to incorporate might suddenly arise. Product managers live for this stuff!

If you want to be a competitive software company, then you want an organization that’s able to react quickly to customer feedback, to changes in your competitive landscape, and to technological evolution. You want the ability to iterate quickly on your product, making changes and shipping them. You want to be agile.

What happens if (a) your product is full of awfulness and (b) you’ve committed your future resources to removing that awfulness? Both of these destroy agility. Lack of quality destroys agility because it makes it difficult to change the product. Future resource commitments destroy agility because you’ve committed the people who would make those changes to working on something else. Taking on technical debt might have the veneer of agility, because it’s first effect is to ship something quickly. But that’s just a veneer. Technical debt makes organizations less agile, not more.

Minimum Viable Implementation

Organizations that maintain both quality and agility do so by creating minimum viable implementations (MVI). An MVI is a "sweet spot" in the compromises articulated earlier that balances quality with development speed. (And other relevant variables, of course.) The work must be good enough that it won’t get in the way of the next change. But the work shouldn’t be better than that, because the sooner it’s done, the sooner the next work can be started.

Conclusion

Technical debt has become a pervasive metaphor in the software world, but it’s deeply flawed. It encourages poor engineering (by skewing compromise) and works against organizational agility. Software development organizations that want to produce good products quickly will do better to set it aside and return to the art of compromise that’s at the core of good engineering.



© 2023 by Oliver Goldman