Technical debt audit findings are what turn a vague engineering complaint into a number a board can act on. Every development team knows its codebase has problems. Far fewer can say what those problems cost per month, which of them is compounding, and which single item deserves the two sprints of remediation capacity anybody is realistically going to approve this quarter.
That gap between felt pain and measured cost is why repair budgets get cut first. “The code is messy” competes badly against a revenue feature with a spreadsheet attached. A technical debt audit closes the gap by producing the spreadsheet: an inventory of debt items, a defensible cost for each, an interest rate showing which ones grow, and a ranked repair queue tied to money rather than to whichever module irritates the loudest engineer.
This guide covers how to run that exercise end to end. It works through what a technical debt audit measures and what it deliberately ignores, the six categories of debt to inventory, the five passes that make up the audit itself, four methods for costing what you find, the metrics that survive contact with a finance director, and how to prioritise repairs by cost of delay. It pairs with our guidance on software maintenance cost after launch, which covers the steady-state budget this work sits inside.
Table of contents
- What a Technical Debt Audit Actually Measures
- Where Technical Debt Hides: Six Categories to Inventory
- How to Run a Technical Debt Audit in Five Passes
- Putting a Price on the Findings: Four Costing Methods
- Technical Debt Audit Metrics That Survive a Board Meeting
- Prioritising Repairs by Cost of Delay, Not by Irritation
- Turning a Technical Debt Audit Into a Funded Roadmap
- Tooling for a Technical Debt Audit, and Where It Stops
- Technical Debt Audit Mistakes That Waste the Whole Exercise
- Technical Debt Audit FAQ
- References
What a Technical Debt Audit Actually Measures
The phrase gets used for everything from a static-analysis report to a three-week consulting engagement. Narrowing it is the first useful step, because a technical debt audit that tries to assess all software quality produces a document nobody reads.
Debt is a deliberate trade, not a synonym for bad code
Ward Cunningham’s original metaphor described shipping something imperfect on purpose to learn faster, then paying the borrowing down. That framing matters during an audit because it separates two things people conflate: code that is poor, and code that was a reasonable decision whose repayment was never scheduled. A technical debt audit inventories both, but it prices them differently — deliberate debt has a known payoff, accidental debt has only cost.
The audit measures cost and interest, not elegance
Every finding in a technical debt audit has to answer two questions: what is this costing us now, and is that cost growing? A module that is ugly, stable, rarely touched and cheap to run is not a priority no matter how much it offends. A tidy-looking service that forces every deployment through a manual gate is. Anchoring on Martin Fowler’s technical debt quadrant keeps the exercise honest about which is which.
Scope it to systems, not to the whole estate
A technical debt audit works best bounded to the systems that carry business risk: the products under active change, the integrations that break, the platforms with an end-of-support date. Auditing everything at once produces a finding list so long it reads as hopeless, and hopeless lists get shelved.
What sits outside the boundary
Feature gaps, product strategy disagreements and roadmap disputes are not debt. Neither is a service that behaves exactly as designed and simply costs money to run — that is a cost optimisation question, and mixing the two makes the debt case harder to argue. Keep the audit to shortcuts, decay and constraint.
Where Technical Debt Hides: Six Categories to Inventory
Most technical debt audit work goes wrong by looking only at source code. Source code is one of six places debt accumulates, and it is rarely the most expensive one. Inventory all six or the total will be wrong by a wide margin.
Code and architecture debt
Duplication, tangled dependencies, god classes, dead branches, and architectural decisions that made sense at one tenth of current traffic. This is the category tooling detects best, which is precisely why it dominates audits that lean on tooling alone.
Test and quality debt
Missing coverage on critical paths, flaky suites that teams have learned to re-run, and manual regression scripts that gate every release. Test debt is expensive because it converts directly into slower change and lower confidence, and it is invisible in a code-quality score.
Infrastructure and deployment debt
Hand-configured servers, unrepeatable environments, pipelines that only one person can fix, and platforms running unsupported versions. This is where a technical debt audit usually finds its largest single number, and it is the category most closely tied to DevOps maturity.
Dependency and platform debt
Libraries several major versions behind, frameworks past end of life, runtimes that no longer receive security patches. The NCSC guidance on obsolete products is blunt about what unsupported software means for risk, and this category carries a hard deadline the others do not.
Data and schema debt
Denormalised tables nobody dares change, columns whose meaning drifted, duplicate sources of truth, and migrations that were never finished. Data debt is the quietest category and the hardest to repair later, because every downstream consumer has adapted to the flaw.
Knowledge and documentation debt
Systems only one person understands, undocumented runbooks, tribal decisions with no recorded rationale. It is the category executives most often dismiss and the one that turns a routine departure into a three-month recovery.
| Category | Typical symptom | How to detect it | Cost signal to capture |
|---|---|---|---|
| Code and architecture | Small changes touch many files | Static analysis, change coupling | Hours per change request |
| Test and quality | Manual regression before release | Coverage on changed lines, flake rate | Person-days per release |
| Infrastructure and deployment | Releases scheduled for weekends | Deployment logs, lead time | Overtime and failed-change rate |
| Dependency and platform | Upgrade blocked by one library | Dependency scan, support calendar | Unpatched severity count |
| Data and schema | Two systems disagree on a figure | Reconciliation exceptions | Hours of manual correction |
| Knowledge and documentation | One named person unblocks everything | Commit concentration, bus factor | Delay when that person is away |
A technical debt audit that produces findings in only one or two of these rows has not finished. The pattern in the right-hand column is the point: every category has to end in a unit finance recognises, not in a severity label.
How to Run a Technical Debt Audit in Five Passes
The mechanics matter less than the sequence. Running a technical debt audit in this order stops the exercise collapsing into a tooling report, which is the most common failure mode.
Pass one: gather the evidence that already exists
Before anybody opens the codebase, pull six months of delivery data: cycle time, change failure rate, incident tickets by system, support escalations, and the list of changes that were estimated small and finished late. This is the raw material every technical debt audit costs its findings from, and it exists already. Teams that skip this pass end up asserting cost rather than demonstrating it.
Pass two: run the automated analysis
Now run static analysis, dependency scanning, coverage measurement and change-coupling analysis across the bounded scope. Treat every output as a hypothesis, not a finding. A technical debt audit that reports a tool’s remediation estimate as fact will be dismissed the first time someone checks one of the entries.
Pass three: interview the people who feel it
Ask engineers a specific question: what did you avoid doing this quarter because of how the system is built? The answers surface constraint debt no scanner detects — the feature deferred, the integration declined, the customer commitment nobody would make. Ask support and operations the same question in their own terms.
Pass four: reconcile the two views
Where tooling and people agree, you have a confirmed finding. Where tooling flags something nobody feels, it is usually noise. Where people report pain the tooling missed, you have found infrastructure, data or knowledge debt — often the expensive kind. This reconciliation is the analytical core of a technical debt audit and cannot be automated away.
Pass five: cost, score and rank
Each surviving item gets a cost, an interest rate, a repair estimate and a risk note before the technical debt audit ranks anything at all. Ranking before costing produces a list ordered by advocacy, which is how the loudest team’s pet refactor reaches the top.
Putting a Price on the Findings: Four Costing Methods
Costing is where a technical debt audit most often loses credibility, usually by quoting a single vast number with no working shown. Use more than one method and state which you used for each item.
Remediation cost: what it takes to fix
The estimated effort to bring an item to an acceptable state, in person-days at a loaded rate. It is the easiest number to produce and the least useful on its own, because it says nothing about whether fixing it is worth doing.
Carrying cost: what it takes not to fix
The recurring drag: extra hours per change, additional testing, incident handling, workarounds, and infrastructure you are paying for only because of the flaw. Carrying cost is what makes the business case for a technical debt audit, because it is money the organisation is already spending.
Interest rate: how fast it grows
Some debt is flat — an ugly module nobody touches costs the same next year. Some compounds, because every new feature built on the flaw increases the eventual repayment. Capturing a direction and a rough rate per item separates the two, and it is the single most persuasive column in the report.
Risk-adjusted exposure: what it costs if it breaks
For unsupported platforms and unpatched dependencies, the honest cost is probabilistic: likelihood of an incident multiplied by its impact. Keep the arithmetic visible and conservative. A technical debt audit that inflates this column to force a decision will be dismantled by the first sceptical reader.
| Method | What it answers | Evidence needed | Weakness |
|---|---|---|---|
| Remediation cost | What would fixing it cost? | Engineering estimate | Ignores whether it is worth fixing |
| Carrying cost | What is it costing now? | Cycle time, incidents, rework | Needs six months of clean data |
| Interest rate | Is the cost growing? | Trend over two or more quarters | Directional, not precise |
| Risk-adjusted exposure | What if it fails or is exploited? | Likelihood and impact estimates | Easy to inflate, easy to dismiss |
| Tool-generated debt ratio | How does the code score? | Static analysis only | Blind to five of six categories |
| Opportunity cost | What did we not build? | Deferred roadmap items | Hard to defend in isolation |
Across the engagements where carrying cost gets measured properly, the distribution is consistently lopsided — the categories teams instinctively blame are rarely where the money goes.
Technical Debt Audit Metrics That Survive a Board Meeting
A technical debt audit full of cyclomatic complexity scores will not get funded. Translate every finding into a metric an executive already uses, and keep the technical measures in an appendix for the engineers who will do the work.
Lead time for change is the headline
How long from a committed change to it running in production, measured for real rather than from the sprint board. It is the metric the DORA research programme has spent a decade validating, and it captures the compound effect of code, test and deployment debt in one number a non-engineer understands.
Change failure rate shows the risk side
The proportion of changes that cause an incident, a rollback or a hotfix. Rising failure rate alongside stable delivery volume is one of the strongest signals a technical debt audit can report: debt is being absorbed as risk rather than paid down.
Unplanned work percentage exposes the drag
The share of engineering capacity consumed by things nobody chose to do: incident response, emergency patches, rework, manual workarounds. Above roughly a third, teams have effectively lost control of their roadmap, and the technical debt audit has its argument written for it.
Debt concentration tells you where to start
The proportion of total carrying cost sitting in the top five findings. In practice a handful of items usually account for most of the spend, which is what makes prioritisation viable at all. Report it explicitly, because it is the number that makes a limited repair budget look sufficient rather than futile.
| Metric | Healthy | Watch | Acting as a brake |
|---|---|---|---|
| Lead time for change | Under one week | One to four weeks | Over one month |
| Change failure rate | Under 15% | 15-30% | Over 30% |
| Unplanned work | Under 20% | 20-35% | Over 35% |
| Time to restore service | Under one day | One to three days | Over three days |
| Unsupported components | None in production | Dated, with a plan | Past end of support |
| Bus factor on key systems | Three or more | Two | One |
Capture each of these before the repairs begin. Without a baseline, a technical debt audit cannot demonstrate that remediation worked, and unprovable improvements do not get funded a second time.
Prioritising Repairs by Cost of Delay, Not by Irritation
Ranking is where a technical debt audit earns its keep. The goal is a queue defensible to both the engineers who will execute it and the executives who will fund it.
Score on four axes, deliberately few
Carrying cost, interest rate, remediation effort and blast radius — how much of the roadmap the item is blocking. Four axes is enough to separate findings and few enough that scoring a hundred items stays feasible. Adding a fifth tends to produce arguments about weighting rather than better decisions.
Compute cost of delay, not a priority label
Divide annual carrying cost plus expected growth by remediation effort, and rank on the result. High, Medium and Low labels invite negotiation; a ratio invites comparison. Where two items score closely, break the tie on blast radius, because unblocking future work compounds in a way that saving hours does not.
Fix what is in the path of the roadmap first
An expensive piece of debt in a system nobody will change for a year can wait. Cheap debt sitting directly under next quarter’s committed features cannot. Aligning the repair queue with the roadmap is what converts an audit into work that actually gets scheduled, and it is the point where strategic IT planning and engineering priorities have to be reconciled in the same room.
Decide explicitly what you will never repair
Every technical debt audit produces findings that are real, costly and still not worth fixing — systems being retired, products in run-off, modules due for replacement. Marking them “accepted, not scheduled” with a named owner and a review date is a legitimate outcome and stops them reappearing in every subsequent review.
| Finding | Carrying cost / yr | Interest | Repair effort | Rank |
|---|---|---|---|---|
| Manual release process | £78,000 | Rising | 25 days | 1 |
| Unsupported database version | £31,000 | Rising sharply | 18 days | 2 |
| No tests on billing path | £44,000 | Flat | 30 days | 3 |
| Duplicated customer records | £26,000 | Rising | 40 days | 4 |
| Legacy reporting module | £19,000 | Flat | 55 days | 5 |
| Admin tool nobody maintains | £9,000 | Flat | Retiring | Accepted |
Notice that the second-ranked item is not the second most expensive. Interest rate moved it, which is exactly what a technical debt audit is supposed to expose — the finding that is cheap today and will not be next year.
Turning a Technical Debt Audit Into a Funded Roadmap
A technical debt audit that ends in a document has failed. The output that matters is a repair plan with capacity attached to it, agreed by the people who control the roadmap.
Reserve a standing percentage, not a one-off project
Debt remediation delivered as a discrete project competes with features and loses. A standing allocation of delivery capacity — commonly 15 to 20 per cent — survives because it is a policy rather than a negotiation each quarter. Teams that run recognisable agile methodologies can carry this as a permanent slice of every sprint.
Sequence repairs against the delivery calendar
Schedule the item blocking next quarter’s largest feature before that feature starts, not alongside it. Repairs done just in time are cheaper because the team is already in that part of the system, and they are easier to justify because the benefit is immediate and visible.
Choose repair, replace or retire per item
Not everything is refactored. Some findings are best resolved by replacing the component, some by retiring it, some by isolating it behind a stable interface and leaving it alone. Our refactor vs rewrite comparison covers where that line usually falls, and the build vs buy vs low-code framework applies when replacement is on the table.
Re-measure on a fixed cadence
Set a review date at the technical debt audit’s close — quarterly for the metrics, annually for a full re-run. A technical debt audit repeated on a schedule produces trend data, and trend data is what converts a one-off argument into a governed process under normal IT governance reporting.
Tooling for a Technical Debt Audit, and Where It Stops
Tools accelerate the second pass of a technical debt audit and contribute almost nothing to the other four. Buying a platform and calling its output an audit is the most expensive shortcut available.
Static analysis quantifies code debt only
Platforms that compute a remediation estimate from rule violations are useful for trend lines and for spotting concentration. Their absolute numbers are model output, not measurement — the SonarQube metric definitions are explicit about how the figures are derived, and quoting them to a board without that context invites a fair challenge.
Repository analytics find the debt that actually costs money
Change coupling, churn concentration and hotspot analysis over commit history identify the files that change constantly and break often, and they are the most under-used input to a technical debt audit. This correlates with carrying cost far better than complexity scores do, because it measures what the team actually touches.
Dependency and licence scanning is non-negotiable
Automated inventory of every dependency, its version and its support status, run per release rather than at audit time. Tools such as OWASP Dependency-Check turn platform debt from an archaeology exercise into a filter, and they give the risk column real evidence.
Delivery metrics need a source of truth
Lead time and change failure rate have to come from the pipeline and incident systems, not from self-reported sprint data. If that plumbing does not exist, building it is itself a finding — an organisation that cannot measure its delivery cannot demonstrate that any repair worked.
| Tooling class | Covers | Misses | Audit pass |
|---|---|---|---|
| Static analysis | Code and architecture debt | Everything outside the repository | Two |
| Repository analytics | Hotspots, coupling, bus factor | Why the pattern exists | Two and four |
| Dependency scanning | Platform and licence debt | Bespoke code quality | Two |
| Delivery metrics | Carrying cost evidence | Which item is responsible | One |
| Interviews and workshops | Constraint and knowledge debt | Objectivity without data | Three |
| Cost modelling | Ranking and business case | Nothing, if inputs are wrong | Five |
Technical Debt Audit Mistakes That Waste the Whole Exercise
These are the failures that turn a fortnight of technical debt audit effort into a document filed and forgotten. Each one is avoidable at the planning stage.
Producing a finding list with no owner
Findings without a named owner and a decision — scheduled, accepted or rejected — decay into background noise. Every row leaves the technical debt audit assigned to somebody, including the rows nobody intends to fix.
Quoting one enormous total
“We have £2.4 million of technical debt” invites disbelief and nothing else. The persuasive framing is granular and recurring: this item costs £78,000 a year, costs 25 days to fix, and is getting worse. Boards fund payback periods, not totals.
Auditing on a cadence nobody agreed
A technical debt audit run once, in reaction to a bad quarter, produces a snapshot with no trend and no mandate. Agree the cadence and the standing capacity allocation before the first pass, so the findings land somewhere that can act on them.
Letting the audit become a performance review
The moment findings read as criticism of named individuals, the interviews stop being useful and the whole exercise turns defensive. Debt is a property of systems and decisions, most of them made under pressure by people who were right at the time.
Mistaking a tooling report for an audit
A scan is pass two of five. On its own it over-weights code, under-weights infrastructure and data, and misses constraint entirely — which is how organisations end up refactoring tidy modules while the deployment process quietly consumes a third of their capacity. Independent technology consulting input helps here, mainly because an outsider will ask about the categories the incumbent team has stopped noticing.
Technical Debt Audit FAQ
How long should a technical debt audit take?
For a bounded scope of one to three systems, two to four weeks including interviews and costing. Anything longer usually means the scope was drawn too wide, and anything shorter has skipped the reconciliation pass where the real findings emerge.
Who should run it?
A small group combining an engineer who knows the systems, someone who owns delivery data, and an independent voice. A wholly internal technical debt audit under-reports the debt everyone has normalised; wholly external ones misjudge which findings are practical to fix.
What is an acceptable level of technical debt?
There is no universal figure, and any consultant quoting one is guessing. The workable test a technical debt audit applies is directional: is carrying cost stable or falling, is unplanned work below about a third of capacity, and is nothing running past end of support? Those three answers matter more than any ratio.
How do we justify remediation to a board that only funds features?
Lead with carrying cost and interest rate, not with code quality. Show what is already being spent, what it will be next year without action, and what one quarter of allocated capacity buys back. A technical debt audit expressed in delivery capacity regained is a growth argument, not a maintenance request.
Should the audit cover third-party and supplier-built code?
Yes, and a technical debt audit often finds the worst of it there, because outsourced work is rarely reviewed for maintainability after acceptance. Include supplier-delivered components in scope and check them against the same six categories, particularly documentation and dependency currency.
What if the audit says the system should be replaced?
That is a valid finding, but it needs its own business case rather than being folded into a repair budget. Compare full replacement cost against several years of carrying cost, and be honest that replacements routinely overrun. Working with a software development company in Chester or any delivery partner, insist that the comparison uses the same costing method for both options.
How often should we repeat it?
Full re-run annually, metrics reviewed quarterly. The value compounds: the second technical debt audit takes considerably less effort than the first because the inventory, the costing model and the measurement plumbing already exist, and the trend line does most of the arguing for you.
Can we run a technical debt audit without any tooling?
Yes, and a manual audit built on delivery data plus structured interviews will beat a tool-only report every time. Tooling makes pass two faster and more repeatable; it does not supply the judgement that the other four passes depend on.
References
Martin Fowler: Technical Debt Quadrant
Object Management Group: Automated Technical Debt Measure Specification
ISO/IEC 25010: Systems and Software Quality Models
DORA: Research and Assessment for Software Delivery Performance
GOV.UK: Managing Legacy Technology
GOV.UK: The Technology Code of Practice
NCSC: Managing Obsolete Products
SonarQube: Code Metrics Definitions
OWASP Dependency-Check Project