Managing technical debt
Every system carries technical debt; the question is whether anyone is managing it. Module 29 showed how to find where a codebase hurts. This module is about what to do next: telling deliberate debt from accidental, measuring the interest it charges, deciding which debt to repay and which to leave, and explaining all of it to people who think in features and money.
1. The idea
Ward Cunningham coined the metaphor in 1992: shipping code that reflects your current, incomplete understanding is like borrowing money. It's fine if you pay it back by refactoring as you learn; the danger is the interest, the extra effort every later change costs because the code no longer matches the problem. The principal is the work needed to fix it.
Four kinds of debt
Martin Fowler's technical debt quadrant separates debt by two questions: did you know you were taking it on, and was it a sensible choice?
| Reckless | Prudent | |
|---|---|---|
| Deliberate | "We don't have time for design." Usually a false saving: the payoff point comes sooner than people think. | "We must ship now and will deal with the consequences." A real trade-off, recorded and planned. |
| Inadvertent | "What's layering?" A team that doesn't know good design builds debt without noticing. | "Now we know how we should have done it." Learning that only comes from building; every good team has this kind. |
Where debt lives
- Code debt: duplication, tangled classes, missing tests. Local and found by tools.
- Architecture debt: a shared database, a synchronous chain, a boundary in the wrong place (Modules 09, 23). Expensive to fix and invisible to code scanners.
- Dependency debt: outdated frameworks and libraries with security fixes you can't take.
- Test and operations debt: manual release steps, flaky tests, missing monitoring.
2. How it works
Interest, quarter by quarter
A team launches a pricing feature three weeks early by copying the price calculation into four places: prudent, deliberate debt. Watch what each later change costs.
Which debt to repay: interest vs principal
A debt register has two candidates. Repay the one whose interest pays back the fix fastest, not the one that offends engineers most.
3. Try it yourself
Set a debt budget
A team delivers 100 units of feature work a quarter when the code is healthy. Today, debt already slows it by 10%. Every quarter of pure feature work adds more drag; time spent repaying removes it. Choose the share of capacity spent on repayment and the time horizon. This is an illustrative model, not a measurement.
4. Trade-offs
Speed now vs speed later
Debt really does buy time: a launch, a deadline, a learning experiment. The cost arrives later and grows. Borrow on purpose, with a note of what and why, and a trigger for repaying it.
Steady budget vs clean-up projects
A standing share of capacity keeps debt flat with little drama. A big "refactoring quarter" is hard to justify, delivers nothing visible, and is often cancelled halfway.
Repay vs live with it
Debt in code nobody touches charges no interest. Leave it. Repay where change is frequent: the hotspots from Module 29.
Refactor vs rewrite
Incremental refactoring keeps delivering while it improves. A rewrite stops the interest only after it ships, and accumulates its own debt on the way. Prefer the strangler pattern for big items (Module 30).
5. In real projects
Keep a debt register. A short list, next to the ADRs: what the debt is, where it is, why it was taken, the interest it's charging (with evidence) and the estimated principal. arc42 reserves a section for it (Module 32). Deliberate debt gets an entry the day it's taken.
Measure interest, not smell. Useful evidence: lead time for changes in that area versus elsewhere, how often it changes (from version control), incidents and rollbacks traced to it, and developers' own estimates of time lost. Static-analysis tools such as SonarQube estimate remediation time per issue; treat those numbers as a guide to principal, not as the business case.
Repay where you walk. The cheapest repayment is done while changing that code for a feature anyway, the "boy-scout rule": leave it a little better than you found it. Bigger items get their own planned work, justified by interest.
Explain it in the business's units. Not "the pricing module is ugly" but "every pricing change takes four days instead of one, we make about ten a quarter, so we lose a month of an engineer each quarter; fixing it costs three weeks."
Say it in the interview
- "How do you handle technical debt?" I record it, measure the interest where it hurts (change frequency times extra effort), and repay the items with the fastest payback, mostly inside feature work with a steady capacity budget.
- "Is technical debt always bad?" No. Deliberate, prudent debt can buy a launch date; the problem is unrecorded debt and debt in code that changes constantly.
- "How do you convince the business?" Translate interest into time and money per quarter, compare it with the cost of the fix, and show the payback period.
- "We'll rewrite it" as the answer to every debt.
- Ranking debt by how ugly the code is rather than by how much it costs.
- "We do a tech-debt sprint once a year."
6. Remember it
How this hook works: what "borrow on purpose, repay where you walk" means
What the slogan means, phrase by phrase
- "Borrow on purpose"
- Prudent, deliberate debt, recorded in the debt register with the reason and a trigger for repaying.
- "repay where you walk"
- Spend repayment effort on hotspots, the code that changes often, ideally while changing it for features.
Why this picture fits: you fix the potholes on the road you drive every day, not on one you never use.
The story → the concept
| The loan | Technical debt |
|---|---|
| Borrowing for the van | A deliberate shortcut to hit a date |
| Monthly interest | Extra effort on every change in that code |
| The principal | The refactoring that removes the shortcut |
| Loans you forgot you took | Inadvertent, unrecorded debt |
The trap it saves you from
Either never borrowing (and missing the market) or never tracking what you borrowed (and slowing to a crawl).
7. Common mistakes
8. Design exercise (30 minutes)
- List five debts (10 min). In a system you know, name five, and place each in the quadrant and in a kind (code, architecture, dependency, test or operations).
- Price them (10 min). For each: changes per quarter in that area, extra days per change, and the cost to fix. Compute the payback period.
- Write the pitch (10 min). Three sentences to a product manager for the item with the fastest payback, in days and money.
9. Self-check quiz
"We'll ship with a single database table for now and split it when we pass 10,000 customers" (written in an ADR). Which quadrant?
In the debt metaphor, what is the interest?
Two debts cost the same to fix. One sits in code changed 40 times a quarter, the other in code changed twice a year. Which first?
Which repayment approach usually works best?
What kind of debt can a static-analysis tool usually not see?
10. Go deeper
| Resource | Time | Why |
|---|---|---|
| Technical Debt Quadrant (Martin Fowler) | 10 min | The four kinds of debt. |
| Technical Debt (Martin Fowler) | 10 min | Interest, principal and why the metaphor works. |
| Debt Metaphor (Ward Cunningham) | 5 min video | The inventor of the metaphor on what he meant by it. |
| arc42 section 11: risks and technical debt | 10 min | How to record debt alongside the rest of the architecture. |