Technical Debt
Date: 2026-08-17
A deliberate shortcut taken to ship sooner, which costs interest until repaid. The metaphor is precise and almost always misused — code you dislike isn’t debt, and calling it that is why engineering requests to “pay down tech debt” don’t get funded.
The original meaning
Ward Cunningham’s metaphor, and the part that gets dropped: debt is borrowed deliberately, against a known benefit, with the intention of repaying.
DEBT NOT DEBT
"we shipped the simpler model to "the previous team used a framework
hit the campaign date. it can't I wouldn't have chosen"
express multi-currency, and we
knew that when we chose it" "this code is ugly"
↑ a decision, a benefit "we don't have tests" ← that's a gap
received, a known cost "the library is 3 major
still being paid versions behind" ← that's neglect
The distinction is practical, not pedantic. Debt has a story a finance director can follow: we borrowed time, we got the campaign, we’re paying interest at roughly two days a sprint. Ugly code has no such story, so it competes with features on aesthetics and loses every time.
The four kinds
Cunningham’s metaphor was later extended into a quadrant — reckless versus prudent, deliberate versus inadvertent — and the four cells need different responses.
| Deliberate | Inadvertent | |
|---|---|---|
| Prudent | ”Ship now, fix after launch” — real debt, manage it | ”Now we know how it should have been designed” — the healthy kind; it’s learning |
| Reckless | ”No time for design” — the expensive one | ”What’s a layered architecture?” — a skills problem, not a debt problem |
Only the top-left is worth the word. The bottom-right is a hiring and training question and gets solved that way; the top-right is unavoidable and fine.
What the interest actually is
Debt is only worth repaying where it’s charging you. Make that concrete:
symptom interest, measured
every price change touches 6 files ~1 day per change, 2× a month
and a production bug roughly quarterly
the checkout has no tests every release needs 3 hours of manual QA
→ 6 hours/month, plus what escapes
one person understands the tax logic 2-week wait when they're on leave
and a hiring risk nobody has priced
the build takes 22 minutes 8 engineers × ~6 waits/day
≈ 17 hours/week of context switching
Debt in code nobody touches is charging nothing. A grim module that has been stable for four years and is never modified can be left alone indefinitely — that’s not negligence, it’s correct prioritisation. Rewriting it is spending money to remove a cost you weren’t paying.
Making it fundable
The reason “we need a sprint for tech debt” fails is that it asks for time without naming a return. What works:
- Attach it to the work it’s blocking. “This feature is three weeks; two of those are the pricing module. Fixing the module first makes this and the next four features one week each” — that’s an investment case
- Quantify the interest in the units above — hours per month, incidents per quarter, days of delay. Not “it’s messy”
- The boy-scout rule for small debt. Leave each touched file slightly better. This handles the long tail and needs no permission
- A standing allocation for the middle band — commonly ~15–20% of capacity, defended rather than negotiated per sprint. The exact figure matters less than it being a default rather than a request
- Never a rewrite. The instinct to replace the whole thing is where debt work goes to die — The Strangler Pattern, Refactoring Strategy
Debt that isn’t code
The forms that get missed because they’re not in the repository:
- Data debt. A schema that made sense before the business changed, denormalised copies nobody reconciles, a column called
type_2— usually the most expensive and least discussed - Dependency debt. Versions drifting far enough behind that upgrading becomes a project rather than a chore. Interest is charged all at once, at the worst moment, when a security patch only exists for a version four majors ahead — Dependency Management, Supply Chain Risk
- Knowledge debt. One person who understands a system. The interest is a bus factor and it’s realised suddenly
- Process debt. A manual deploy step, a release checklist someone maintains by hand
- Measurement debt. Instrumentation that no longer matches the product, so decisions are made on numbers that quietly stopped meaning what they say — Metric Drift, Tracking Plans
Where it interacts
- Refactoring Strategy — how repayment actually happens, in steps that stay shippable
- Deprecation — removing the thing the debt is attached to, which is sometimes cheaper than fixing it
- Feature Flags — a large and reliable source of debt in their own right, since every unremoved flag is a permanent branch
- Code Review — where reckless-deliberate debt is either caught or waved through