The Tech Lead Handbook · Quality and Delivery

Managing Technical Debt Deliberately

Make technical debt visible, decide which debt to pay down, and protect a steady budget for it — with a model of how debt 'interest' eats delivery capacity.

Scenario

Example team: the payments team ships features every sprint. Tests are slow, the refund module is a 3,000-line file, and two services share a database table. Every quarter the team asks for a "tech debt sprint"; product says "after the launch". The launches keep coming.

What you see on the team

  • Estimates for changes in old areas are 2–3x those for new code.
  • The same modules cause most incidents and most review debate.
  • "Tech debt" tickets with no description of impact, which product can't prioritise.
  • Occasional big clean-up sprints that are cancelled or rushed.

The common mistake

Treating technical debt as one undifferentiated backlog paid off in rare clean-up sprints, argued about in engineering terms product can't weigh.

Why it happens

Debt's cost is spread across many small slowdowns, so it's invisible in any single sprint. Feature work has a visible owner and deadline; debt work doesn't. Martin Fowler's Technical Debt Quadrant is a useful reminder that not all debt is equal: deliberate, prudent debt ("ship now, deal with consequences") is a legitimate trade-off; inadvertent, reckless debt is not.

The playbook

1. Keep a debt register with impact, not just descriptions:

Item Where it hurts Cost today Fix effort Interest if ignored
Shared payments table between services Every schema change needs 2 teams ~1 day/change, 2 incidents last quarter 3 weeks Grows with each new consumer
Slow test suite (25 min) Every PR ~6 engineer-hours/day waiting 1 week Grows with tests

2. Prioritise by interest: fix what you touch often and what causes incidents. Leave stable, rarely touched mess alone.

3. Protect a steady budget — e.g. 15–20% of each sprint — instead of rare clean-up sprints. Steady budgets survive launches; debt sprints don't.

4. Pay down alongside features: when a feature touches a debt hotspot, include the clean-up in the estimate.

5. Report outcomes in product terms: "test time 25 → 9 minutes", "refund changes now take 2 days instead of 5".

The model below compares a team that never pays down debt with one that spends 20% steadily:

Debt interest: 0% vs 20% paydown over a yearTry it yourself
WEEKS = 52
CAPACITY = 100.0  # team capacity units per week

def run(paydown_share):
    debt = 30.0       # % of capacity lost to friction at the start
    delivered = 0.0
    for week in range(1, WEEKS + 1):
        effective = CAPACITY * (1 - debt / 100)
        feature = effective * (1 - paydown_share)
        delivered += feature
        debt += 0.6                                  # new debt from feature work
        debt -= paydown_share * effective * 0.08     # paydown reduces friction
        debt = max(5.0, min(60.0, debt))
        if week in (13, 26, 39, 52):
            print(f"  week {week:2}: friction {debt:4.1f}%  feature work this week {feature:5.1f}"
                  f"  cumulative {delivered:6,.0f}")
    return delivered

for share in (0.0, 0.2):
    print(f"paydown {share:.0%}:")
    run(share)

Output

paydown 0%:
  week 13: friction 37.8%  feature work this week  62.8  cumulative    863
  week 26: friction 45.6%  feature work this week  55.0  cumulative  1,625
  week 39: friction 53.4%  feature work this week  47.2  cumulative  2,285
  week 52: friction 60.0%  feature work this week  40.0  cumulative  2,845
paydown 20%:
  week 13: friction 22.6%  feature work this week  61.5  cumulative    762
  week 26: friction 13.4%  feature work this week  68.7  cumulative  1,610
  week 39: friction  5.0%  feature work this week  76.0  cumulative  2,561
  week 52: friction  5.0%  feature work this week  76.0  cumulative  3,549

In this (illustrative) model, the 20% team delivers less feature work at first, matches the other team after about half a year, and then pulls clearly ahead, because its friction falls while the other team's keeps growing. The exact numbers depend on your team — the shape is the point: steady paydown is an investment that pays back within months, not years.

What to say

To product, with numbers:

"Our test suite costs about six engineer-hours a day in waiting. A week of work brings it from 25 to under 10 minutes. I'd like to keep 20% of each sprint for items like this from the register — here are the top three and what each buys us."

Trade-offs

  • A fixed percentage is simple but blunt; adjust it each quarter based on the register.
  • Paying down debt in stable code wastes effort; prioritise hotspots.
  • Deliberate debt to hit a real deadline is fine — record it in the register with a payback plan.

Signals it's working

  • The register exists, is current, and items leave it.
  • Estimates for hotspot areas come down over time.
  • Fewer incidents in previously debt-heavy modules.
  • Product can name the top debt items and why they matter.

Key points

  • Keep a debt register with impact, cost and interest, not just descriptions.
  • Prioritise debt you touch often or that causes incidents; leave stable mess alone.
  • Protect a steady budget (often 15–20%) rather than rare clean-up sprints.
  • Report paydown in product terms: time saved, incidents avoided.

Practice questions

Product keeps postponing your 'tech debt sprint'. What do you propose instead?

Answer

A debt register with impact and cost, a steady budget of roughly 15–20% per sprint, paydown bundled with features that touch hotspots, and reporting in product terms such as time saved and incidents avoided.

Which debt should you pay down first?

Answer

Debt with the highest 'interest': code changed often, code that causes incidents, and friction every engineer hits daily (slow tests, slow deploys). Stable, rarely touched code can stay messy.

Is taking on technical debt ever the right call?

Answer

Yes — deliberate, prudent debt to meet a real deadline is a valid trade-off, as long as it's recorded with a payback plan. Reckless or inadvertent debt is the problem.

Open in the app to mark lessons complete, take notes and track your progress.