{ } Programming

Technical debt: what it is, how to spot it and pay it back

Technical debt explained concretely: where it comes from, warning signs, how to measure it, explain it to decision makers and pay it back steadily.

The expression "technical debt" was introduced by Ward Cunningham to explain to non-programmers a dynamic familiar to every developer. When you choose a quick solution instead of a well-structured one, you get an immediate advantage, like a loan. But from that moment on you pay interest: every subsequent change in that area of the code costs a little more. If the debt is never paid back, the interest grows until it slows down all the work.

Not all debt is a mistake

The metaphor is useful precisely because debt, in itself, is not negative. A company can knowingly borrow to seize an opportunity. In the same way, a team can choose a temporary solution to meet an important deadline or to quickly check whether an idea interests users.

A useful distinction, proposed by Martin Fowler, crosses two questions: was the debt taken on deliberately or through inexperience? And prudently or recklessly?

Reckless Prudent
Deliberate "We don't have time for design" "We ship now and fix it after the launch"
Inadvertent "What's layering?" "Now we know how we should have done it"

The last box is unavoidable: working on a system teaches you things, and with hindsight you see a better structure. The problem is not having debt, but not knowing about it or not managing it.

Where it comes from

The most common sources:

  • shortcuts under pressure: duplicated code instead of a shared function, values hard-coded, edge cases ignored;
  • lack of tests: every change becomes risky, so people avoid improving the code;
  • outdated dependencies: libraries untouched for years, whose upgrade becomes ever harder and riskier;
  • changed requirements: the code suited the problem of two years ago, not today's;
  • lost knowledge: whoever wrote the module has left and nobody dares touch it.

The warning signs

Technical debt is rarely visible from looking at the code once. You recognise it by its effects on daily work:

  1. changes that should take an hour take a day;
  2. fixing one bug causes others in apparently unrelated areas;
  3. there are parts of the system everyone avoids modifying;
  4. new team members take weeks to become productive on a certain module;
  5. estimates become less and less reliable, because nobody knows what lies behind a change.

Making it visible

Debt that exists only in developers' heads cannot be managed. The first step is to record it. A practical approach:

  • create specific items in the work tracking system, with a dedicated label;
  • for each item, describe the problem, the affected area and above all the cost it produces: "every new payment method requires changes in five different files and about three days of manual testing";
  • roughly estimate the effort to resolve it.

The cost is the most important part, because it is what lets you talk to whoever sets priorities. A product manager will hardly approve "rewrite the payments module because it is ugly", but will understand perfectly "we can cut the time to add a payment method from three days to half a day".

How to pay it back

Halting development for months to "clean everything up" is rarely possible and often counterproductive. Continuous strategies work better:

  • the campsite rule: every change leaves the touched area a little cleaner;
  • a fixed share: a stable portion of each work cycle dedicated to debt;
  • pay back where you work: prioritise debt in areas that will be changed soon, because that is where interest is paid;
  • leave the rest alone: an ugly but stable module that nobody has touched for years generates no interest. Improving it has little value.

The last point is counterintuitive but fundamental. Debt should be measured by the friction it generates, not by the aesthetics of the code.

Avoiding new debt

Some practices limit debt at the source: mandatory automated tests, code review, regular dependency upgrades in small steps, and above all the habit of recording deliberate shortcuts immediately. A comment in the code with a reference to the tracking item takes a few seconds and prevents the temporary solution from becoming permanent through forgetfulness.

In short

  • Technical debt is the future cost of shortcuts: it is paid as interest on every change.
  • Not all debt is a mistake; the problem is failing to recognise and manage it.
  • You recognise it by its effects: slow changes, cascading bugs, areas nobody wants to touch.
  • Record it by describing the cost it produces, so its priority can be discussed.
  • Pay it back continuously, starting from the areas of code that change most often.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. With degrees in computer science and psychology, he combines technical analysis with an understanding of the human factor.

Read also