SlamData

Practice

Technical Debt: Measuring It Instead of Complaining About It

The metaphor implies a deliberate loan, and most of what gets called debt was never borrowed. How to make the cost visible enough to fund.

The metaphor came with a specific meaning: you ship something knowingly imperfect to learn sooner, and you pay interest until you fix it. A deliberate trade, taken with awareness.

For a separate people-operations application of the same measurement discipline, see time tracking software.

What the term now covers is mostly not that. It covers code nobody understands, decisions that made sense under different constraints, dependencies that aged, and work that was simply done badly.

The distinction matters because the arguments differ. A deliberate loan has a repayment case. Accumulated mess has an interest payment nobody has calculated, and that is why the request to address it never wins against a feature.

Four things called by one name

Deliberate and prudent. "We know the right design; we are shipping the simpler one to validate demand." Real debt, taken knowingly, with a plan.

Deliberate and reckless. "No time for design." Also real, and the interest is higher because nobody wrote down what the shortcut was.

Accidental. The design was reasonable and the requirements moved. Not a mistake, and it still costs.

Rot. Dependencies aged out of support, the platform moved, the tooling stopped being maintained. Not caused by any decision — caused by time — and it is the category most likely to become urgent suddenly, because a security advisory sets the schedule.

Only the first has a natural repayment moment. The others need a deliberate one, and this is why "we will fix it later" never happens: there is no later without a decision.

Make the interest visible

The reason debt work loses to feature work is that features have estimated value and debt has an anecdote. Fix the asymmetry with numbers you already have.

Time to change. How long does a typical change in this area take, against a comparable area? A team that can add an endpoint in a day in one module and a week in another has a measurable difference, and the week is the interest payment.

Change failure rate by area. Which parts of the system produce incidents when touched? Version control plus your incident record gives you this.

Rework. Changes that required a follow-up fix within a fortnight.

Onboarding time. How long before a new engineer can safely change this area. Ask the last two people who joined; the answers are specific and uncomfortable.

Refusal. The strongest signal and the easiest to observe. Which changes get quoted so high that the business stops asking? A capability the company has effectively lost is worth more than any code metric.

Build and test time, which taxes every change by every person, compounds silently, and is trivially measurable.

Dependency age and support status. Countable, and it converts rot into a date.

Making the argument

Translate into the outcome the audience owns. Not "this module has high coupling" but "changes here take four times longer and cause two thirds of our incidents."

Tie it to something wanted. The strongest case is not "let us pay down debt" but "the roadmap item you want requires touching this area, and doing it as-is costs three times as much." Debt work attached to a feature gets funded; debt work as a separate ask does not.

Give a bounded proposal. "Two engineers for three weeks, and afterwards changes in this area take days rather than weeks." Open-ended refactoring is unfundable and rightly so.

Say what happens if it is deferred. Not as a threat — as a forecast, with the interest rate you measured.

Paying it down without a rewrite

The full rewrite is almost always the wrong answer. It takes longer than estimated, delivers no value until the end, and reproduces bugs whose reasons nobody recorded. The exception is a system small enough to rewrite in weeks.

Strangle instead. Route new functionality through a new implementation, migrate existing paths one at a time, and delete the old part when nothing uses it. Value arrives continuously and it can be stopped halfway with the work so far still useful.

Fix what you touch. Improving the area you are already working in costs a fraction of a dedicated project, because the context loading is already paid for.

Put a boundary around it before improving the inside. A stable interface in front of a bad module lets you replace the inside later without coordinating with every caller. Frequently the highest-return first step.

Delete. Unused code, dead feature flags, abandoned endpoints, retired configuration. This is the cheapest debt reduction available and it requires no design work — just the confidence to remove something, which usage data provides.

Fix rot on a schedule. Dependency updates are cheap when routine and expensive when a security advisory sets the deadline. A regular slot beats an emergency every time.

What not to do

Do not track a "debt backlog" nobody prioritises. A list of 200 items that never shrinks is a monument, not a plan.

Do not use a static-analysis debt score as the goal. These tools estimate remediation hours from rule violations, and the number is not connected to any cost you actually pay. Useful as a hotspot indicator; meaningless as a target.

Do not allocate a fixed percentage and consider the problem handled. "20% for tech debt" without prioritisation means the easy items get done and the expensive ones — which are the ones with the interest — do not.

Do not rewrite because the code is unpleasant. Unpleasant and expensive are different, and only the second justifies the spend.

Preventing the next round

Write down deliberate shortcuts when you take them, in the code, with the reason and what the proper version would be. A comment saying "simplified for launch; proper version needs X because Y" is worth more than any backlog ticket, because it is where the next person will be.

Record decisions and their reasoning. Most accidental debt is expensive because nobody knows why the current design exists, so nobody can tell what is safe to change.

Keep dependencies current continuously.

Delete aggressively, and treat unused code as a cost rather than an asset.

The summary

Most of what is called debt was never borrowed, which is why it has no repayment date.

Measure the interest with data you already have — time to change, failure rate by area, work the business stopped asking for.

Attach the work to something wanted, and bound it.

Strangle rather than rewrite, fix what you touch, and delete what nothing uses.

The argument is lost by asking for time to make the code nicer, and won by showing what the current state costs in the terms the person deciding actually owns.

For primary background on this topic, consult Technical Debt reference.