The real cost of technical debt: what it does to month six

The real cost of technical debt: what it does to month six

Almost everything written about technical debt is written for developers. This is written for the person paying for the development, because that is who the cost lands on and they are usually the last to hear about it.

The metaphor is doing less work than it appears to. Debt implies you knew what you borrowed and on what terms. Most of what accumulates in a codebase was never a decision. It is the residue of a hundred reasonable choices made under time pressure, none of which were wrong at the moment they were made.

What makes it worth your attention is not that it exists — every product has it, and a product with none was probably built too slowly. It is that some of it compounds and some of it does not, and almost nobody separates the two.

What you will actually see

Technical debt rarely announces itself. It shows up as a pattern in things you were already tracking.

Estimates stop being reliable, and specifically they stop being reliable in one direction — everything takes longer than the team expected, including the team. The same bugs return after being fixed. Releases become events that require everyone present rather than routine. Your developers start describing work as risky, and begin proposing ways to add features alongside the existing code rather than inside it. New people take months to become useful.

Any one of those has innocent explanations. Several at once is a structural problem, and the useful question is not whether the code is messy but whether the cost of change is rising.

The shape of the cost

Here is the part that matters for a budget, and the reason the month-six framing is the right one.

Take a feature of a fixed size — the same amount of actual product, built at three different points in a system’s life.

In month one it slots in. The code is small, one person holds the whole thing in their head, and there is nothing to work around.

In month three it needs a little scaffolding. Something adjacent has to be adjusted first, a test has to be updated, there is a short conversation about where it belongs. Perhaps a third more effort than month one.

By month six the same feature arrives with an apparatus around it. Two adjacent modules need changing because the boundary between them was never clean. A workaround from month two has to be unpicked first. Nobody is certain what else touches the thing being modified, so the change is made cautiously and tested broadly. Someone has to be present who remembers why it was built that way.

The feature has not grown. The cost of installing it has, and it will keep growing, because the scaffolding added this month becomes next month’s thing to work around.

That is the compounding part, and it is why the arithmetic feels wrong when you look at it later. You are not paying for messy code. You are paying for the fact that the price of every future change went up.

Debt that compounds, and debt that just sits there

This distinction is the most useful thing on this page, because it is where the money is.

Compounding debt is anything that other work has to route around. A data model that does not fit the business, because every new feature inherits the mismatch. Missing or untrustworthy tests, because every change becomes manual verification. An unclear boundary between two parts of the system, because every feature touching either one touches both. An unsupported framework version, because every library you want next assumes something newer.

Debt that sits there is contained. An ugly module that works and that nobody needs to change. Duplicated code in a corner of the product nobody is extending. An inconsistency in naming. These offend engineers and cost you almost nothing, and paying them down is a hobby rather than an investment.

If an engineer proposes a cleanup, the question is not whether the code is bad. It is whether anything you intend to build next has to pass through it. If nothing does, it can wait indefinitely.

Why it is hard to see from where you sit

Two structural reasons, and neither is anybody acting badly.

The first is that the cost is distributed. There is no invoice for technical debt. It arrives as a slightly larger number on every estimate, and a slightly larger number is always explicable by something else — this feature was complex, that sprint had holidays, the requirements changed. By the time the trend is visible in aggregate, it has been true for a year.

The second is that your team has adapted to it. Developers working in a difficult codebase become expert at working around its difficulties, and that expertise makes the difficulty invisible. They stop mentioning the thing everyone knows. The clearest signal is often a new hire, who will say out loud in week two what the existing team stopped saying in month four.

What to do about it

Not a rewrite. That is the most expensive option available and it is right far less often than it is proposed — it stops all delivery, carries real risk of arriving worse, and usually reproduces the same mistakes with newer tools.

What works is unglamorous.

  • Find out which kind you have. An audit that separates compounding from contained is the difference between spending usefully and spending to feel better.
  • Pay down the compounding items only, and only where they block something. Fix the data model if the roadmap keeps hitting it. Leave the ugly module alone.
  • Attach it to work you were doing anyway. Improving the area a new feature touches, as part of that feature, is far easier to fund and far less disruptive than a cleanup project.
  • Stop the bleeding first. If there are no tests on a critical path, adding them is cheaper than any refactor and makes everything after it safer.
  • Ask for the cost, not the condition. “This code is bad” is not actionable. “This will add two weeks to every feature in this area” is.

What to ask your team on Monday

Three questions that usually surface more than a code review would.

  1. If you had to add a significant feature to this product, which part would you be most reluctant to touch, and why?
  2. What takes longer now than it did a year ago, and what changed?
  3. If something broke in production tonight, what would be hardest to diagnose?

The answers tend to converge on the same two or three areas. Those are your compounding debt, and they are where any money is worth spending.

If the estimates have stopped making sense

Tell us what you are seeing. We will tell you what we think is underneath it, and what it would take to find out properly, before anyone signs anything.

Related reading

Previous Article
What a mobile app costs, broken down by module
Previous Article
Next Article
How to audit an AI-generated codebase before you build on it
Next Article

Let’s talk about your project

welcome@ideus.biz