Tech Debt Management
Purpose
Make hidden tech debt visible so it can be prioritized and repaid. Untracked debt compounds silently; tracked debt is just a backlog item.
Universal — the inventory + impact×effort + sprint-budget pattern applies to any codebase; tool names (grep patterns, deprecated APIs) vary by stack.
Procedure
Inventory comment-flagged debt
- Find all in-code debt markers (TODO / FIXME / HACK / XXX)
- Classify each: still relevant? actionable? stale?
- Classify the kind (Fowler's quadrant): deliberate vs inadvertent × prudent vs reckless — a prudent-deliberate shortcut ("ship now, refactor post-launch") is a tracked loan; reckless/inadvertent debt signals a process or knowledge gap to address differently
- Delete stale ones; categorize the rest into the debt registry
- Going forward, require attributable markers —
// TODO(owner, TICKET-123): ...(a lint rule can forbid bare TODOs) so debt links to the tracker
Inventory type-system escape hatches
- Locate all type bypasses (TS
any/as any, Python# type: ignore, etc.) - For each: justified (with comment) or accidental?
- Prioritize removal of unjustified escapes in hot paths
- Locate all type bypasses (TS
Inventory deprecated dependencies and APIs
- Major-version migrations pending (framework, libraries)
- Replacements for unmaintained deps
- Legacy patterns (deprecated lifecycle hooks, removed APIs)
- Check package-manager
outdatedreport
Identify untested business logic
- Coverage report → list files/branches with 0% coverage
- Cross-reference with business-criticality (auth, payment, data integrity = high risk)
- Untested + critical = top of repayment list
Score each debt item: Impact × Effort
Low effort High effort High impact 🟢 Do now 🟡 Plan a project Low impact 🔵 Backlog 🔴 Delete from list - Impact = user-facing risk, dev velocity drag, or compounding cost (favor debt that slows every future change over one-time costs)
- Effort = engineer-hours
- Weight Impact by change frequency (git churn): debt in a file touched weekly costs far more than debt in code untouched for a year — a hotspot is high churn × high complexity (
git logchurn, CodeScene) - Debt that has already caused an incident or bug is proven high-impact — mine the bug tracker
Document in
TECH-DEBT.md(ordocs/exec-plans/tech-debt-tracker.mdif using craft-kit conventions)- One section per item: description, location, impact, effort, status (open / scheduled / done)
- Sort by Impact × Effort (top of doc = highest leverage)
- ⚠ A standalone debt doc rots — nobody opens it. Use it for triage, but promote scheduled high-impact items into the real backlog / issue tracker (linked) so debt competes with features in planning, not in a doc no one reads
Allocate 15-20% sprint capacity to debt
- Otherwise it never gets paid
- Beyond the budget, repay opportunistically: when you touch a file for a feature, clean the debt you encounter there (boy-scout rule). Don't proactively repay debt in stable, rarely-touched code that works — repay what's in your path or actively slowing you
- Track Technical Debt Ratio (TDR) as a leadership-facing metric — common formula:
TDR = (fix-cost) / (build-cost from scratch) - [OPINION] The exact TDR formula varies across sources (SQALE, CAST Software, internal company definitions). Treat as an industry-common heuristic, not a standard. Use whatever formulation is meaningful in your org and document it.
- Translate friction to annualized hours for leadership: "10 min/day workaround = ~40 hrs/year per dev" — this framing converts soft "annoyance" into hard cost
Schedule quarterly review
- Re-score items (effort estimates often change as code evolves)
- Move stale items to "won't fix" with reason
- Promote new items spotted during normal work
Completion Criteria
-
TECH-DEBT.mdlists every known debt item with impact × effort score (Impact weighted by change frequency) - Top 5 high-impact items have a scheduled repayment plan AND are promoted to the real backlog/tracker
- Stale TODO/FIXME deleted or reclassified; remaining TODOs are attributable (owner + ticket)
- Quarterly review on the calendar
Stop & Ask (AI must pause for user approval)
- Before deleting any TODO/FIXME comment — even if it looks stale; the author may have context AI doesn't
- Before re-categorizing an item from "open" to "won't fix" — explicit team decision required
- Before bulk-removing
anytypes — some may be intentional pending downstream library types
Output
- Registry:
TECH-DEBT.md(ordocs/exec-plans/tech-debt-tracker.mdif using craft-kit conventions) with table:- Item / Location / Impact (1-5) / Effort (S/M/L) / Status / Owner
- Impact × Effort matrix: visual 2x2 in the same file
- Quarterly review entry: dated subsection listing re-scored items + new items + closed items
- Annualized friction memo (for leadership): one-pager summarizing top 5 items as hours/year lost
Implementation
React + Next.js (default)
- Comment grep:
grep -rEn 'TODO|FIXME|HACK|XXX' src/ - TS
anygrep:grep -rEn ': any($|[^a-zA-Z])|as any' src/ - Common deprecated patterns: Pages Router → App Router,
moment→date-fns/dayjs, class components → hooks,componentDidMount→useEffect - Dep status:
npm outdatedorpnpm outdated - Coverage:
vitest run --coverage
Other stacks
- Vue / Nuxt: same grep; deprecated: Options API → Composition API for new code; Vue 2 → Vue 3 migrations
- SvelteKit: same grep; deprecated: Svelte 4 reactivity → Svelte 5 runes
- Angular: same grep; deprecated:
NgModule→ standalone components;@Input()→input()signal - Generic: the universal procedure stands alone — only the language-specific grep patterns and dep-management commands change
Related skills
code-refactoring— most debt is paid down through refactoring passesdecision-records— large debt items deserve an ADR for the migration approach
Reference
- Key insight encoded: Reserve 15-20% sprint capacity for debt as a budget item, not a "when we have time" hope. Use Technical Debt Ratio (TDR = fix-cost / build-cost) as the leadership-facing metric — it shows that debt compounds. Triage with impact × effort matrix weighted by change frequency (debt in hot files costs most) and start with low-effort/high-impact wins to build trust. Two senior judgments: repay debt that's in your path (boy-scout rule) rather than proactively cleaning stable code that works, and promote scheduled items into the real backlog — a standalone debt doc nobody opens just rots.
- Caveat: This is the weakest-referenced skill in the toolkit — open-source standards in this space are thinner than in technical domains. Cite both sources and treat as an evolving practice.