How would you make technical debt visible and decide which items to pay down first?
answer
- Register: principal, interest, trigger, owner
- Prioritize by interest rate, not ugliness
- Hotspots = churn x complexity
- Overlay the roadmap
- Blocking debt is scope, not cleanup
basics
~20 sWrite debt down where the team and stakeholders can see it, with the fix cost and the pain it causes. Then fix first the items in code you change often, because those cost you repeatedly.
solid answer
~50 sMake it explicit: a debt register (backlog items, an architecture decision log, or annotated tickets) where each entry states the current design, the target design, the estimated principal, the observed interest and a repayment trigger. Scattered TODO comments do not count - they are invisible to planning. Then prioritize by *interest rate*, not ugliness: expected pain over the horizon you care about. Practically, combine change frequency (version-control churn per file or module) with complexity or defect density to find hotspots - code that is both messy and constantly touched - and overlay the roadmap so debt beneath upcoming features ranks higher. Static-analysis remediation estimates give a principal figure but say nothing about interest, so they must not set the order alone. Track blocking debt separately: items that make a planned feature impossible or unsafe are prerequisites, not optimizations.
go deeper
Say debt should be written down as real backlog items rather than left in comments, and fixed first where the team works most often.
Add explicit inputs - churn, complexity, defect density - and that priority follows recurring cost rather than size.
Describe a register template with principal/interest/trigger, hotspot analysis, roadmap overlay, and separating blocking debt from optional cleanup.
Cover governance: keeping the register small, avoiding tool-driven ranking, quantifying interest in delivery terms, and guardrails so new debt is detected early.
## Step 1 - make it explicit Debt that lives only in developers' heads never competes for capacity. Options in increasing order of usefulness: - **Code markers** (TODO/FIXME) - cheap, but invisible to planning and never expiring. - **Debt register / backlog items** - each written as a change with a cost, not a complaint. - **Architecture decision records** - for deliberate debt, recording what you chose *not* to build and why. - **Dashboards from static analysis** - continuous, but they measure symptoms, not cost of change. A useful item template: *current state, target state, why it hurts (with evidence), estimated principal, observed interest, repayment trigger, owner*. ## Step 2 - prioritize by interest, not ugliness The scarce resource is engineering time, so the ranking question is "which repayment buys the most future capacity?" Key inputs: 1. **Change frequency** - from version-control history. Code changed weekly multiplies any friction; code frozen for years does not. 2. **Complexity / smell density** - a proxy for cost per change. 3. **Defect density and rework** - where incidents and hotfixes actually originate. 4. **Roadmap overlap** - debt sitting under the next two quarters of work has a much higher effective interest rate than debt elsewhere. 5. **Blast radius / risk** - debt in security, data-integrity or availability paths carries tail risk beyond delivery slowdown. **Hotspot analysis** - intersecting churn with complexity, popularized as behavioural code analysis - is the standard technique. It concentrates attention on the small fraction of files where most change happens. ## Step 3 - separate the categories - **Blocking debt** - the feature cannot be built safely without it; this is scope of the feature, not optional cleanup. - **High-interest debt** - slows everything; schedule deliberately. - **Dormant debt** - ugly but untouched; leave it, revisit if it becomes a hotspot. - **Debt in code about to be deleted** - paying principal there is waste. ## Pitfalls - **Tool-driven ordering.** Remediation-cost models in static-analysis tools produce a principal in days but have no notion of how often the code changes; ranking by that number sends teams to fix dead corners. - **A giant debt backlog.** Hundreds of stale items become noise; prune aggressively and keep it current. - **Registers with no economics.** "This class is horrible" cannot be prioritized against a revenue feature; "changes here take three days instead of one, about eight times a quarter" can. - **Measuring debt by line count or coverage percentage.** Both correlate weakly with cost of change.
- Why is ranking debt by a static-analysis 'remediation effort' score risky?That score estimates principal only. It ignores change frequency, roadmap overlap and risk, so it can rank a large dormant module above a small hotspot the team fights weekly. Use it as a cost input, never as the ordering key.
- How do you present debt priorities to a product manager?In delivery terms: 'these three items sit under the next two quarters of roadmap; each feature there currently costs roughly 40% more and carries higher rollback risk. Five days of work removes that surcharge.' Tie it to their commitments, not to code aesthetics.
- What signals suggest a codebase is approaching technical bankruptcy?Estimates inflating for comparable work, a rising share of capacity spent on incidents and rework, features regularly blocked by unrelated modules, fear-driven change avoidance, and long-lived branches because integration has become too painful.
saying these in an interview costs you the question
- Relying on TODO/FIXME comments as the debt tracking system
- Ranking debt by size or ugliness rather than by how often the code changes
- Treating a static-analysis debt score as the prioritization order
- Maintaining a huge, stale debt backlog nobody grooms
- Presenting debt as a purely technical quality argument with no delivery consequence