Technical debt is the most-discussed engineering concept with the least agreed measurement, and the reason is that it is not one thing. A deliberate shortcut taken to hit a date, an architecture that no longer fits the product, a dependency three major versions behind, and a module written by someone who left in 2023 are four different problems that share a label.
So any single number claiming to quantify it is aggregating incommensurable things. What works instead is measuring the symptoms, which are specific, located, and priceable.
Why the debt score fails
Static analysis tools will give you a composite figure — a grade, a remediation estimate in days, a debt ratio. It is tempting because it is a single number that leadership can track.
Three problems with it.
It aggregates severity badly. A thousand style violations and one unguarded SQL concatenation contribute to the same total, and the total tells you nothing about which to fix. Teams end up fixing whatever moves the number most per unit effort, which is the style violations.
It does not correlate with pain. The highest-scoring area of a codebase is frequently a module nobody has touched in two years, where the debt is real and costing nothing because the code is stable and finished. Meanwhile the area actually hurting may score well because it is heavily tested and heavily modified.
And a single number invites a target. Once there is a target, the cheapest way to move it gets found quickly, and it is usually not the work that would help. The general mechanism is productivity theatre; this is a particularly expensive instance because the gaming consumes engineering time.
Four proxies that earn their place
Each of these is observable from systems you already run, and each produces a finding with a location attached.
Change cost by area. The strongest single signal. Take comparable changes — a new field, a new endpoint, a new report — and compare how long they take in different parts of the system. When one area consistently costs four times another, you have found debt with a price. This is the form that funds work, because it converts a quality argument into an arithmetic one.
Defect concentration. Where do incidents and bug fixes cluster? Pull the last six months of incidents and map them to the components involved. Debt that causes outages is a different priority from debt that is merely ugly, and this separates them.
Change coupling. Which files change together even though they should not be related? High coupling across what ought to be module boundaries is architectural debt made visible, and it is computable from your version control history without anyone's opinion.
Avoidance. The softest proxy and often the most telling. Which areas do engineers route around, pad estimates for, or quietly decline to pick up? This is tacit knowledge that never reaches a dashboard, and asking the team directly surfaces it in ten minutes. It also tends to identify the same areas as the first two, which is a useful corroboration.
The debt that does not matter
Worth saying plainly, because debt discourse tends toward the absolutist: a lot of technical debt is correctly left unpaid.
Code that is stable, has no planned changes, is adequately tested and causes no incidents is not costing you anything, regardless of how it scores. Rewriting it converts zero ongoing cost into real present cost plus the risk of new defects in something that currently works.
The question is never "is this debt" but "is this debt we are paying interest on". Interest is paid in slower change, more incidents, slower onboarding, and engineers avoiding the area. Debt with no interest payment is a fact about the codebase rather than a problem with it.
This is also why change cost is the best primary proxy: by construction it only flags areas where someone is actually trying to make changes.
How it connects to delivery metrics
Debt shows up in DORA measures before anyone names it as debt. Lead time drifts upward, change failure rate rises, time to restore lengthens because the system is harder to reason about under pressure.
Those tell you something is wrong system-wide. The proxies above tell you where, which is what makes them complementary rather than redundant — and flow efficiency sits in between, since debt-heavy areas generate more review cycles and more blocked time per item.
Onboarding is the other place it surfaces early and clearly. If a new engineer takes markedly longer to ship in one area, that area has a cognitive-load problem, which is debt in the form that costs most per head. The time to productivity piece covers measuring the ramp, and the developer experience lens covers cognitive load as a dimension in its own right.
What to actually do
Pick the two or three areas that appear in more than one proxy. Overlap between high change cost, high defect concentration and engineer avoidance is a much stronger signal than any single measure, and it is usually a short list.
Then scope the work as a bounded change with a stated expected benefit, and measure whether the benefit arrived. If change cost in that area does not fall after the work, that is worth knowing — sometimes the diagnosis was wrong, and a rewrite that does not reduce change cost has produced nothing but risk.
Resist the urge to measure everything. The value here is in acting on two findings, not in maintaining a debt inventory.
Where ProdView fits
Honestly: this is mostly not our data. Change cost, defect concentration and change coupling come from version control, your incident record and your issue tracker. We cannot see code and would be overreaching to claim otherwise.
Where ProdView contributes is the human side of the same question — where engineering attention concentrates, where context switching spikes, and whether a particular team's focus time is being eaten by firefighting. A team whose fragmentation climbs while delivery slows is often a team fighting a specific part of the system, and that is a prompt to go and look rather than a measurement of the code.
When not to pick us: if you want code-level debt analysis, buy a tool that reads the code, or compute the proxies above from your own repositories. Both are better instruments for this than activity data.
Try before you commit
Three seats are free forever, though for this question the cheaper first move is pulling six months of incidents and mapping them to components. That costs nothing and usually names the area before any tooling does.