How to Measure Technical Debt in a Repo
You cannot pay down what you cannot see. Here is how I measure technical debt in a real repo using churn, coupling, and change cost instead of vibes.
To measure technical debt you have to stop treating it as a feeling and start treating it as a cost. Technical debt is the gap between how long a change should take and how long it actually takes because of past shortcuts. Measure that gap and you can prioritize it, budget for it, and defend paying it down. Leave it as a vibe and it stays an argument nobody wins. Here is how I put real numbers on it.
Measure change cost, not code ugliness
The mistake almost everyone makes is measuring the code instead of the effort. They count long functions and deep nesting and call it debt. But ugly code that never changes costs nothing. Debt is only real when it slows a change you actually need to make.
So the base unit is change cost. Take a recent set of changes and ask how long each took relative to its size. A one-line business rule change that required touching eight files and a day of testing is expensive debt. The same change in a well-factored module takes twenty minutes. The difference between those two numbers is the debt, expressed in the only currency that matters: time. I go deeper on this framing in what a code quality score actually measures, because the two questions are the same question.
Use churn times complexity to find the hotspots
You cannot read every file, so let the data point you. The formula I trust is churn multiplied by complexity. Churn is how often a file changes. Complexity is how tangled it is. Multiply them and you get a hotspot list.
A file that is complex but stable is dormant debt, ignore it for now. A file that is simple but changes constantly is fine. The dangerous quadrant is high churn and high complexity: code that is hard to change and that you are forced to change all the time. That is where your debt payments actually go, week after week, and it is usually a handful of files carrying most of the load. ReformCode computes this across a whole repo automatically, which is the only sane way to do it at scale.
Quantify coupling as blast radius
The second measurable driver is coupling: how much breaks when you touch one thing. Measure it by tracing which files change together in your git history. If editing the pricing module reliably forces edits in checkout, reporting, and the mobile client, those things are coupled whether or not the code admits it.
Blast radius is a number you can track. Count the average files touched per logical change over time. If that number is climbing, your debt is compounding. If it is falling, your cleanup is working. This is far more honest than any static metric, because it measures what the codebase does under real pressure instead of what it looks like at rest.
Put a currency on it
None of this matters to a business until it has a dollar sign. So convert. Take your worst hotspots, estimate how much slower they make a typical change, multiply by how often that change happens and by a loaded engineering cost. Now you have annual carrying cost per hotspot.
That number changes every conversation. Instead of an engineer saying the code is messy and a manager hearing complaining, you have a line item: this module costs roughly a quarter of an engineer per year in avoidable friction. Now the fix has a payback period, and payback periods get funded. This is the same discipline that lets me ship SaaS faster on a shared foundation: I know exactly what each shortcut costs to carry.
Track the trend, not the snapshot
A single debt measurement is nearly useless. Debt is only meaningful as a direction. Measure the same repo every month and watch whether carrying cost is rising or falling under your current investment level.
That trend is the real management dashboard. It tells you whether your cleanup budget is winning or just slowing the bleed. A repo with high but falling debt is healthier than a clean repo whose numbers are quietly climbing. Snapshots flatter or scare you. Trends tell the truth.
What to do once you can see it
Measuring debt is only worth it if it changes what you do. Once the numbers are in front of you, the moves are obvious. Fund the top three hotspots, ignore the dormant complexity, and put a small standing budget against the trend so it never runs away. That is the whole point of measuring debt: to spend cleanup effort where it pays back instead of wherever the loudest engineer points.
Debt you cannot see gets moralized about and never fixed. Debt you can measure gets prioritized like any other cost. Turn it into churn, coupling, and carrying cost, and the argument turns into a plan.