Maintenance economics
A ledger based on interest, not embarrassment
Record where the cost appears and what would reduce it. This turns ‘the codebase is messy’ into a portfolio of decisions that can compete fairly with feature work.
Unknown critical behavior
Interest paidEvery change requires rediscovery and broad manual checking
Visible signalOnly one person can explain payments, permissions or data mutation
Duplicated business rules
Interest paidFixes land in one path while another silently diverges
Visible signalThe same validation or price logic appears in several components or routes
Oversized generated components
Interest paidUnrelated UI, data and effects change together
Visible signalSmall features produce large diffs and surprising regressions
Unowned dependency growth
Interest paidUpdates, bundle cost and supply-chain review compound
Visible signalMultiple packages solve overlapping jobs or have no known reason
Missing negative-path evidence
Interest paidIncidents reveal requirements for the first time
Visible signalOnly successful demos and snapshot tests exist
Deployment knowledge outside the repository
Interest paidRecovery depends on memory and manual dashboard state
Visible signalNobody can reproduce production or list required secrets
Do not start with a rewrite
First stabilize what users already depend on
A rewrite removes visible mess but also removes years of discovered edge cases. The safer first move is to observe current behavior, identify critical journeys and place tests around the parts you intend to change. Refactoring becomes valuable when it shortens a known feedback loop or removes a measured failure mode.
AI-assisted cleanup can accelerate mechanical work, but large diffs recreate the review-volume problem that caused the debt. Keep migrations reversible, compare behavior and stop when the promised cost reduction does not appear.
- Tie every debt item to a recurring cost or material risk
- Name a smallest useful reduction
- Preserve behavior before improving structure
- Close ledger items only after verifying the expected benefit
Decision matrix
Prioritize debt by product consequence
Style consistency matters, but it should not outrank a fragile permission boundary or unrecoverable data path.
| Debt class | User consequence | Business consequence | First intervention |
|---|---|---|---|
| Security boundary | Exposure or unauthorized action | Breach, loss of trust or regulatory impact | Enforce and test the boundary now |
| Data integrity | Lost, duplicated or inconsistent records | Support load and irreversible correction | Add invariants, backups and recovery tests |
| Operational opacity | Longer outages and unclear errors | Slow response and concentrated knowledge | Instrument critical journeys and assign alerts |
| Change friction | Features and fixes arrive slowly | Engineering time compounds | Characterize behavior and isolate one seam |
| Cosmetic inconsistency | Uneven experience | Brand and conversion cost | Fold cleanup into related product work |
Working sequence
A four-week debt reduction rhythm
This is intentionally compatible with product work. Each week produces an operational asset, not only cleaner code.
Inventory
- Map critical journeys and owners
- Record repeated delays and incidents
- Rank cost, consequence and confidence separately
Stabilize
- Add characterization and negative-path tests
- Document deployment and recovery
- Remove exposed secrets and urgent boundary failures
Create seams
- Separate policy from presentation
- Consolidate one duplicated rule
- Reduce one oversized dependency or component
Measure
- Compare change time and regression rate
- Verify build, bundle and incident signals
- Keep, revise or stop each intervention
Plain answers
Technical-debt questions
Is all generated code technical debt?+
No. Debt describes future cost and risk. Clear, tested and owned generated code may be easier to maintain than poorly understood hand-written code.
Should we measure debt by lines of code?+
Line count can describe size but not interest. Track change time, regressions, incident recovery, duplicated decisions and ownership gaps instead.
When is a rewrite justified?+
When the current architecture cannot meet essential requirements and an incremental path has been tested and found inadequate. The rewrite still needs migration, parity and rollback evidence.