agile / agile-techdebt · v1.0

Technical Debt Management

How to identify, classify, measure, and pay down technical debt within the rhythm of sprint delivery — without stopping the product.

4
Debt quadrants
20%
Recommended capacity
3
Paydown strategies
6
Detection signals

What is Technical Debt?

Technical debt is the implied cost of rework caused by choosing an easy solution now instead of a better one that would take longer. Like financial debt, it accrues interest — small problems become systemic if left unpaid.

Ward Cunningham coined the metaphor in 1992. The key insight: debt isn't inherently bad. Deliberate, short-term debt can be a rational business decision. Inadvertent debt accumulating silently is what destroys velocity over time.

Tech debt ≠ bad code. It is a decision to ship something less-than-ideal now in exchange for speed. The problem is when the "later" to fix it never arrives.

The Debt Quadrants

Martin Fowler's quadrant classifies debt along two axes: deliberate vs. inadvertent, and reckless vs. prudent.

RecklessPrudent
Deliberate"We don't have time for design" — knowingly cutting corners"We must ship now and deal with consequences later" — conscious tradeoff
Inadvertent"What is layered architecture?" — didn't know better"Now we know how we should have done it" — discovered in hindsight
Only Prudent-Deliberate debt is managed well. Reckless debt is simply negligence. Inadvertent debt is addressed through learning and refactoring.

Types of Technical Debt

🏗
Architectural Debt
Wrong structural decisions: monolith that should be services, missing abstraction layers, tightly coupled modules.
High impact
🧹
Code Debt
Duplicated code, long functions, missing tests, poor naming — issues caught in code review but deferred.
Common
📦
Dependency Debt
Outdated libraries, deprecated APIs, unmaintained packages with security vulnerabilities.
Security risk
📝
Documentation Debt
Missing ADRs, outdated READMEs, undocumented APIs — knowledge lives only in people's heads.
Ops risk
🧪
Test Debt
Low coverage, flaky tests, missing integration tests — the safety net has holes.
Quality risk
🚀
Infrastructure Debt
Manual deployments, missing monitoring, no alerting, environments that drift from production.
Reliability

Detection Signals

Technical debt reveals itself through measurable symptoms. These are the signals to track:

1. Cycle time increasing         → features take longer than they used to
2. Bug rate increasing            → more defects per sprint than 6 months ago
3. Onboarding time increasing     → new engineers take months to contribute
4. Fear of change                 → team avoids certain modules
5. Test suite runtime increasing  → CI pipeline slowing down quarter on quarter
6. "Simple" features aren't       → "small" stories consistently pull in hidden complexity
The key measurement: track the ratio of time spent on new features vs. rework and firefighting. If rework exceeds 30% of sprint capacity, debt is actively degrading delivery speed.

Tracking Debt

Untracked debt is unmanaged debt. Teams need a lightweight system to make debt visible to the PO and stakeholders without turning it into a second backlog.

Option 1 — Tech Debt Backlog (pragmatic)
→ Separate backlog section labelled "Technical Enablers"
→ Each item has: description, impact (High/Med/Low), estimated cost
→ PO reviews and prioritises against feature work each sprint
→ Target: process at least 2–3 items per sprint

Option 2 — Debt Tags in existing backlog
→ Tag user stories that include hidden debt ("carries-debt")
→ Linked remediation stories created immediately
→ Remediation scheduled within 2 sprints

Option 3 — Debt register (spreadsheet/wiki)
→ ID, type, description, discovery date, owner, estimated hours
→ Reviewed at Sprint Retrospective monthly
→ Items scoring High impact + Low cost → next sprint

Paydown Strategies

StrategyHow it worksBest for
Boy Scout RuleLeave code cleaner than you found it. Refactor opportunistically when touching a module.Code debt, incremental improvement, low-risk
Allocated capacityReserve 15–20% of sprint capacity for debt items. Scheduled every sprint, not ad hoc.Teams with consistent debt accumulation
Hardening sprintDedicated sprint (once per quarter) with no new features — only refactoring, tests, documentation.Heavy debt; major architectural changes
Strangler Fig patternGradually replace a problematic system component without a big-bang rewrite. New code wraps old.Architectural debt; legacy systems
Feature flags + parallel buildsNew architecture built in parallel; traffic migrated incrementally; old code deleted when safe.Infrastructure debt; high-risk replacements

Capacity Allocation

Recommended allocation by debt level:

Low debt  (healthy codebase): 10–15% per sprint
Med debt  (slowing delivery): 15–25% per sprint
High debt (firefighting mode): 25–40% per sprint

Making it visible to stakeholders:
→ Frame debt work in terms of delivery impact
   "We're spending 30% of each sprint fighting fires from this module.
    2 sprints of focused refactoring will reduce that to <5%."
→ Show trend: feature throughput going DOWN = debt going UP
→ Compare "debt cost" to "feature opportunity cost"
Never negotiate away all debt time. Teams that promise 100% feature delivery have nowhere to go when debt slows them down — and they always slow down.

Prevention Practices

Architectural Decision Records (ADRs)
→ Document the context and reasoning behind key technical decisions
→ Format: Title / Status / Context / Decision / Consequences
→ Stored in the repo; updated when decisions change

Definition of Done — tech quality gates
✓ Code reviewed by at least one other developer
✓ Unit test coverage meets team threshold (e.g. 80%)
✓ No new Sonar/linting violations introduced
✓ Dependencies updated if touched
✓ ADR created for any new architectural decision

Regular "debt audits"
→ Once per quarter: review tech debt register
→ Identify highest-impact items
→ Schedule at least one hardening sprint per year

Anti-Patterns

Anti-PatternProblemFix
Debt as invisible workStakeholders don't know it exists; velocity looks fine until it crashesMake debt visible in the backlog with business impact framing
Debt sprint once a year12 months of accumulation requires months to pay down; not sustainableAllocate 15–20% every sprint; continuous paydown
Complete rewriteSecond-system effect; new system has all the hidden business logic errors the old one solvedStrangler Fig pattern; incremental replacement
Blaming the previous teamDemoralises; doesn't fix the debt; misses the systemic causeBlameless retro; understand why the debt accumulated
Debt as developer excuse"We can't ship because of tech debt" without dataQuantify: show cycle time trends, bug rates, rework %
No DoD quality gatesNew features ship with embedded debt from day oneDoD must include code quality, test coverage, no regression

Tech Debt Cheat Sheet

Quadrants
Deliberate + Prudent  → managed tradeoff; pay back soon
Deliberate + Reckless → negligence; address immediately
Inadvertent           → fix through refactoring and learning

Types
Architectural · Code · Dependency · Documentation · Test · Infrastructure

Detection signals
→ Cycle time increasing
→ Bug rate increasing
→ Rework >30% of sprint capacity
→ "Simple" stories aren't simple

Capacity allocation
Low debt   → 10–15%/sprint
Medium     → 15–25%/sprint
High debt  → 25–40%/sprint

Paydown strategies
Boy Scout Rule      → refactor opportunistically when touching code
Allocated capacity  → 15–20% every sprint, non-negotiable
Hardening sprint    → quarterly, no new features
Strangler Fig       → incremental architectural replacement

Prevention
→ ADRs for all architectural decisions
→ DoD includes quality gates
→ Quarterly debt audit