Ward Cunningham's debt metaphor has been repeated so often that it's stopped carrying information. Most people using it mean roughly "code I don't like, that I would like time to change."
Taken literally, though, it's precise and useful. Debt has three properties, not one, and knowing which you're talking about changes the entire conversation.
Property | In finance | In a codebase |
|---|---|---|
Principal | The amount borrowed | The work required to fix it properly. A one-off |
Interest rate | What you pay to keep carrying it | The tax on every change that touches the affected area. Recurs forever |
Maturity | When it must be settled | The event that forces the issue: an audit, a scaling limit, a dependency going unsupported |
Now notice which one every technical debt discussion is actually about. "How long would the refactor take?" is a question about principal — and principal is the least decision-relevant of the three, because you pay it once and then stop, whereas interest is paid every sprint until you do.
Nobody decides whether to pay off a loan by asking only how large it is. They ask what it's costing to carry. Engineering discussions almost never ask that, and then wonder why they lose.
How do you actually measure the interest?
You don't need new tooling, and this is the part most teams skip because it feels like it should be hard.
Estimate inflation. Take work touching the affected area and compare estimate to actual against work elsewhere. A consistent multiple is your interest rate, expressed in the unit your organisation already plans in
Review rounds per pull request. Changes in a difficult area need more passes, and this is already recorded in your tooling
Incidents attributable to the area, and mean time to resolve them. Cook's point about multiple contributing faults is the mechanism — debt raises the number of latent faults available to combine
Onboarding time to first meaningful change in that area, against elsewhere. This one is expensive to measure and very persuasive, because it prices the knowledge concentration nobody wants to admit to
Work declined. The features not attempted because touching that module is too risky. Hardest to quantify, and frequently the largest term
The first is the one to start with. "Work in this module takes about twice as long to deliver as work elsewhere, and here are the last twelve tickets" is a sentence a non-technical manager can act on, and it required no new instrumentation — only that somebody bothered to look. There is a whole operational layer above technical debt that XenGrowth's growth operations team documents.
Stripe's survey gives the industry-scale version: 13.5 hours of a 41.1-hour week on technical debt plus 3.8 on bad code, roughly 42%. It's self-reported and I'd hold the exact figure loosely, but as an order of magnitude it tells you what a large accumulated interest payment looks like across a profession. For the the operations side of this angle, see The XenGrowth resource library.
The accounting reason nobody sees it
There's a structural explanation for why this cost stays invisible to the people allocating budgets, and it isn't indifference.
On a profit and loss statement, hosting and support sit in cost of goods sold, above the gross profit line. Engineering salaries sit in R&D, below it, as operating expense. So the entire cost of maintaining a system — the 42% — is recorded as investment in building the product rather than as a cost of running it.
The consequence is that a product with a crushing maintenance burden reports an excellent gross margin, indefinitely, with no line anywhere on the statement that gets worse as the debt accumulates. The convention isn't wrong — building a product genuinely is an investment — but it means the statement is structurally blind to the thing your team lives with every day, and no amount of financial reporting will surface it. For the AI agents and marketing automation angle, see XenGrowth on AI agents and marketing automation.
Which means somebody has to say it out loud, in numbers, or it will not be represented at all.
The kinds of debt, and why they behave differently
Cunningham's original metaphor described something narrower than the way it is used now. He meant deliberately shipping a design you knew was not quite right in order to learn from real usage, then paying it back once you understood the domain properly. That is a genuine engineering strategy and it works — the debt is taken knowingly, for a return, with an intention to repay.
Most of what gets called technical debt is not that. It is the residue of decisions made with less information than the people making them realised they lacked, or of deadlines met by deferring work nobody wrote down. Distinguishing the two matters because they respond to different treatment: deliberate debt has a known shape and a plan attached, and accumulated residue has neither, which is why an inventory is usually the first useful thing anyone does.
A third category is worth naming separately because it is the one that actually causes crises. Some debt is not a quality problem at all — it is a bet on an assumption that has since stopped being true. A schema that encoded a business rule which changed, an integration built around a partner's API that has been deprecated, a scaling design premised on traffic patterns that no longer hold. This is not messy code and no amount of tidying addresses it. It is a structural mismatch between what the system assumes and what the world now does, and it tends to surface suddenly rather than gradually.
The practical value of separating these is that they argue differently. Deliberate debt argues on its original terms: we said we would come back to this, here is the return we got, here is the bill. Residue argues on interest, which is the measurement work above. Structural mismatch argues on risk and on maturity, because its cost is not a steady tax but a discontinuity waiting for a trigger.
Not all debt should be repaid
This is the part that makes the rest of your argument credible, and it's the part engineers most often skip.
Debt on code that is stable, isolated and rarely touched has an interest rate near zero. Ugly code that nobody modifies costs nothing to carry, regardless of how much it offends you. Debt in a module scheduled for deletion in six months should never be repaid — you would be paying principal on a loan about to be forgiven.
Situation | Interest rate | What to do |
|---|---|---|
Ugly, stable, nobody touches it | ≈ Zero | Nothing. Leave it alone and stop mentioning it |
Messy, changed every sprint | High and compounding | Repay. This is where the whole argument lives |
Fine now, approaching a scaling limit | Zero, but a maturity date | Schedule it against the date, not against how it feels |
Unsupported dependency, working | Zero until a CVE, then infinite | Treat as a maturity, not as debt. It is a deadline |
Duplicated in five places | Rising — GitClear's measured trend | Repay before the fifth copy diverges from the other four |
Bad, but in a module being deleted | Irrelevant | Nothing. Paying it is pure waste |
Being the engineer who says "that one isn't worth fixing" is what buys you credibility when you say the next one is. A team that describes all of its code as debt is not making an argument, it is expressing a preference, and finance can tell the difference. XenGrowth on AI search, GEO and discovery approaches this from the AI search, GEO and discovery side.
How to say it so it lands
The translation is mechanical once you have the interest figure. Stop describing the code, which asks for trust; describe the effect, which asks for a decision.
Lead with the interest, in local units. "Work in billing takes about twice as long as equivalent work elsewhere" — with the tickets to back it — beats any description of the code
Name the principal as an investment with a payback period. "Six weeks of work, and we recover that in about eight months of avoided drag" is a proposal in a form they already evaluate
State the maturity if one exists, and be honest when it doesn't. A real deadline — a dependency going end-of-life, a scaling limit with a date — is the strongest argument available and is squandered by being mixed in with preferences
Show what it is blocking. Work declined because a module is too dangerous to touch is usually the largest cost and the one nobody has written down
Bring the list of debt you are recommending against fixing. This is the step that makes the whole thing credible, and it is free
One thing to watch for in the current environment: GitClear's numbers show duplication rising while refactoring collapses, which means principal is being added faster while repayment falls. If that pattern holds inside your own repository — and it is straightforward to check — then the interest rate on your codebase is rising, and an argument you lost last year is worth making again with this year's numbers.
Further reading from XenGrowth
The XenGrowth resource library — what you'll learn: how the commercial side of this work is run, across search, automation and revenue operations.
XenGrowth on AI agents and marketing automation — what you'll learn: how the teams who own AI agents and marketing automation plan and measure it.
XenGrowth on AI search, GEO and discovery — what you'll learn: how the teams who own AI search, GEO and discovery plan and measure it.
Where this work meets go-to-market
Working on technical debt inside a commercial team? the XenGrowth practice publishes operator guides on the revenue side of this work.
And if you take one habit from this, make it the inventory rather than the argument. A list of your team's debt with an estimated interest rate against each item, reviewed quarterly, converts an ongoing complaint into a managed position — and it means that when a maturity date does arrive, you are the person who saw it coming rather than the one explaining afterwards why nobody did.






