Technical Debt Assessment and Remediation
Debt named, priced and ranked. Which parts are costing you delivery speed right now, which are dormant, and what it takes to bring the expensive ones back inside tolerance.
- Who
- Founder holds the engineering leadership seat; the delivery team executes underneath it.
What you're seeing
- Estimates for work in one part of the system are consistently three times what they are elsewhere.
- Usually means That module is the debt, and the team has already priced it — informally, in every estimate. Making the number explicit turns a shared grievance into a budget line.
- A dependency is out of support and nobody has scheduled the upgrade.
- Usually means It is deferred because it delivers nothing visible. It stays deferred until a CVE makes it urgent, at which point it is done under pressure and without a test suite anyone trusts.
- The rewrite conversation comes up every quarter and never resolves.
- Usually means Neither the rewrite nor the incremental path has been costed, so the argument is between two intuitions. It will keep recurring until somebody puts engineering months against both.
- Onboarding a new engineer to one service takes twice as long as to the others.
- Usually means Complexity that regular contributors have absorbed and stopped noticing. Ramp time is the least biased measurement of it available, and nobody usually records it.
Debt is a cost, not a judgement
Calling code bad starts an argument, and it is an argument engineering loses. The counterparty is a roadmap with revenue attached, and “this is unpleasant to work in” does not compete with that.
Saying that one module absorbs a fifth of review time, produces a third of the failed deploys, and adds two weeks to every feature that touches it starts a decision instead. Same code, same problem, different conversation — and the second one gets funded.
So the register is built from observable cost. Change frequency and defect rate per module come out of version control. Review time comes out of the same history. Incident attribution comes from whatever record exists. Each item on the list arrives with a number, and items with no number do not arrive.
Dormant debt is cheap
A module nobody has touched in two years costs nothing, however old it looks.
This is the finding teams resist most, because the oldest and ugliest part of a system is the one everyone can name, and being told to leave it alone feels like being told the complaint was not real. The complaint is real. It is just not expensive, and the modernization budget is finite.
The heat map is the useful artefact here: change frequency on one axis, defect rate on the other. The top-right quadrant is where the money goes. The bottom-left is where old code lives quietly and should be left to.
Shippable steps
The repayment plan is ordered so that each step leaves the system working and better than before.
That constraint rules out the most satisfying version of the plan — the one where a new structure is built alongside and switched to at the end. It rules it out for a practical reason rather than an aesthetic one: a programme that only pays at the end has to survive every reprioritisation between now and then, including the funding round, the enterprise deal and the two senior departures nobody has scheduled.
Steps that pay incrementally can be stopped after any one of them. That is what makes it possible to start.
Where it sits
This is a capability under Engineering Velocity when the debt is what is slowing delivery, under Technical Due Diligence when a buyer needs it priced rather than fixed, and part of the five-day Engineering Audit in compressed form.
It is usually run alongside two others. Architecture Review asks the forward-looking version of the same question — this prices what has accumulated, that asks whether the structure holds under what is planned. And DORA Metrics supplies the cost side of the register, because the numbers that make debt fundable are the same four numbers that describe delivery.
How the work runs
-
Inventory
Dependency age, unsupported runtimes, modules with the highest change frequency and the highest defect rate. Measured from version control rather than from memory.
-
Attribute cost
Each item joined to what it actually costs — review time, failed deploys, incidents, the features it makes expensive. Debt with no cost attached is not debt, it is just old code.
-
Separate dormant from active
Old code nobody touches is cheap to leave alone. The rewrite budget belongs to the code that is changed weekly.
-
Sequence the repayment
An ordered plan where each step ships independently and leaves the system working, because a modernization that only pays off at the end usually does not get there.
What arrives
- A ranked debt register with a cost against each item
- Change-frequency and defect heat map by module
- A repayment sequence in independently shippable steps
- An effort range for each step, with what happens if it is skipped
What it costs your team
Around four hours from your engineers: one session to walk the codebase, one to review the ranking.
How we decide
Every item carries an observed cost or it is not on the register
Costs Some genuinely unpleasant code does not make the list, which engineers find hard to accept.
Calling code bad starts an argument that engineering loses, because the counterparty is a roadmap with revenue attached. Saying that one module absorbs a fifth of review time and produces a third of failed deploys starts a decision instead. Debt with no attached cost is not debt; it is old code, and old code that nobody touches is free.
Dormant debt is left alone
Costs It means shipping a report that recommends doing nothing about the oldest, ugliest part of the system.
A module untouched for two years costs nothing however it looks, and the modernization budget is finite. Spending it on code that is not in anyone's way is the most common way these programmes fail to produce a measurable result. The budget belongs where change frequency and defect rate are both high.
Repayment is sequenced into independently shippable steps
Costs It is slower in total than a clean-sheet rewrite would be if the rewrite went perfectly.
A modernization that only pays off at the end has to survive every reprioritisation between here and there, and it usually does not. Steps that each leave the system working and better mean the programme can be paused after any one of them without having wasted the ones before it.
Where this has run
Frequently Asked Questions
Sources
- Martin Fowler — Technical Debtmartinfowler.com
- Martin Fowler — Strangler Fig Applicationmartinfowler.com
- DORA — State of DevOps reportdora.dev
Page reviewed

