Managing technical debt
Make debt visible and tracked, distinguish deliberate from accidental debt, quantify its cost in business terms, pay it down continuously (boy-scout rule + dedicated capacity) rather than via mythical big rewrites, and prevent new debt with standards and reviews.
Technical debt is the gap between the code you have and the code the problem now needs. Managing it well is about visibility, prioritization, and steady repayment — not heroics or rewrites.
1. Make it visible
Invisible debt is unmanaged debt.
- Track it like any other work — tickets, a debt backlog,
// TODO/// HACKannotations that get harvested. - Note it when you create or discover it, with context: what's wrong, why, what it's costing.
2. Classify it
Not all debt is equal (Fowler's quadrants):
- Deliberate & prudent — "we shipped fast for the deadline, here's the cleanup ticket." Fine, if tracked.
- Deliberate & reckless — "no time for design." Avoid.
- Accidental — "now we know how it should've been built." Inevitable; learn from it.
The deliberate, tracked kind is a legitimate tool. Untracked debt is the problem.
3. Prioritize by cost, in business terms
Debt matters when it slows delivery, causes bugs, or blocks features. Frame it for stakeholders that way:
- "This module causes ~30% of our incidents."
- "Every feature here takes 2x longer because of X."
- "We can't ship Y until we refactor Z."
High-impact, high-interest debt first; debt in stable, rarely-touched code can often be left alone.
4. Pay it down continuously — not via a rewrite
- Boy-scout rule — leave code a little better than you found it, as part of normal work.
- Dedicated capacity — a standing % of each sprint, or recurring "tech health" allocation. Continuous beats a someday-big-bang.
- Opportunistic — refactor the area you're already changing for a feature.
- Strangler-fig for big legacy chunks — incrementally replace, don't stop-the-world rewrite. Big rewrites are high-risk and usually fail.
5. Prevent new debt
- Standards, linters, reviews, good architecture, tests — the cheapest debt is the kind you don't create.
- A definition of done that includes quality.
6. Communicate with stakeholders
- Don't ask for "refactoring time" — connect it to velocity, reliability, and roadmap risk.
- Be honest about tradeoffs when taking on deliberate debt.
The senior framing
Debt is a normal part of engineering, not a moral failing — the skill is managing the interest rate: keep it visible, prioritize by business cost, repay continuously, and prevent the reckless kind. Anyone proposing a full rewrite as the answer usually hasn't managed the debt; they've ignored it.
Follow-up questions
- •How do you justify paying down debt to a product manager?
- •Why are big-bang rewrites usually a bad idea?
- •What's the difference between prudent and reckless technical debt?
- •How do you decide which debt to pay down first?
Common mistakes
- •Leaving debt invisible and untracked.
- •Proposing a big rewrite instead of incremental repayment.
- •Asking for 'refactoring time' instead of framing it in business impact.
- •Trying to fix all debt, including in stable code nobody touches.
Performance considerations
- •
Edge cases
- •Debt in code that's about to be deleted (don't bother).
- •Debt that blocks a critical roadmap item (escalate priority).
- •A startup intentionally taking on debt for speed.
- •Debt nobody understands anymore (archaeology before refactor).
Real-world examples
- •Strangler-fig migration replacing a legacy module incrementally behind a stable interface.
- •A standing 15-20% sprint allocation for tech health, plus boy-scout cleanups in feature work.