How to Prioritize Which Tech Debt to Fix First
Not all tech debt is worth fixing. Here is how to prioritize which technical debt to pay down first using interest, blast radius, and your actual roadmap.
Fix the tech debt that charges you interest, and ignore the rest. That is the entire priority rule, and it cuts against the instinct to fix the ugliest code you can find. The ugliest code is often the cheapest to leave alone, because if you never touch it, it never costs you anything. The debt worth paying down is the debt in code you have to keep changing, weighted by how much breaks each time you change it. Here is how I turn that into an actual ordered list.
Rank by interest, not by ugliness
Debt has a principal and an interest rate, just like money. The principal is how bad the code is. The interest is how often that badness taxes you, which is how often you have to work in it. A horrifying module you edit twice a decade has near-zero interest. A merely mediocre module you edit every sprint bleeds you continuously.
So the first sort is by churn. Pull the change frequency for every file and put the frequently-changed ones at the top of the candidate list. The rarely-changed files drop off the list entirely, no matter how bad they look, because fixing them is spending real effort to reduce a cost you were not paying. I build the underlying measurement in how to measure technical debt in a repo, and this is where that measurement pays off.
Weight by blast radius
Among the high-churn files, the tiebreaker is blast radius: how much breaks elsewhere when you change this one. A high-churn file that is nicely isolated is annoying but contained. A high-churn file that is coupled into ten other modules is where your outages and your slow releases both come from, because every edit ripples.
Measure blast radius from history by looking at which files change together. The ones that drag a crowd of other files along on every edit are your top priority, because fixing their coupling makes every future change in that whole neighborhood cheaper. You are not just cleaning one file, you are shrinking the ripple for everything connected to it.
Align with the roadmap you actually have
Now overlay your plans, because debt only matters where you are about to work. If the next two quarters are all about payments, then debt in the payments path is urgent and debt in the settings page is irrelevant, even if the settings page scores worse. Priority is not a property of the code alone, it is the code crossed with where you are headed.
This is the step most debt lists skip, and it is why so much cleanup feels unrewarding: teams fix debt in code they then do not touch for a year. Point the effort at the debt sitting directly in front of your roadmap and every fix immediately makes the work you were going to do anyway faster and safer. It is the same discipline that lets me ship SaaS faster on a shared foundation: cleanup aimed at the next build, not at some abstract ideal of tidiness.
Estimate payback before you commit
For each surviving candidate, do the quick math. Roughly what does this debt cost per year in slower changes, and roughly what does it cost to fix. That gives you a payback period, and payback period is the cleanest way to order a list because it is the language the business already uses for every other investment.
Fix the short-payback items first. A tangle that costs a quarter of an engineer a year and takes two weeks to fix is an obvious yes. A tangle that would take three months to fix and saves a few days a year is an obvious no, even if it is genuinely bad code. Feelings about code quality do not survive contact with a payback calculation, and they should not. ReformCode does this ranking across a whole repo so I am arguing over numbers instead of aesthetics.
Leave the dormant debt alone, on purpose
The last discipline is the hardest: deliberately not fixing debt that does not charge interest. Engineers hate leaving ugly code alone. But cleanup effort is finite, and every hour spent beautifying dormant code is an hour not spent on the hotspots that are actively slowing you down.
Leaving good-enough code alone is not laziness, it is allocation. This is the practical face of treating debt as a balance sheet rather than a confession. You manage the position, you pay down the expensive parts, and you let the cheap parts sit. Prioritizing tech debt well is mostly about having the discipline to ignore most of it so you can actually fix the part that matters.