Technical Debt Works Like a Loan
Once or twice a year a company asks me to look at their system, and within the first hour someone says the words full rewrite. Changes take forever. Every fix breaks something else. The team is tired of the codebase, and starting fresh feels like the only way out.
The last time this happened, we measured before we answered. The repository history told a story nobody in the room expected. Over the previous year, more than 80 percent of all changes touched roughly 15 percent of the code. The remaining 85 percent just sat there, ugly and reliable, doing its job.
That one measurement changes the whole conversation, because it separates the debt you are paying for from the debt you are not.
I have sat on both sides of this. I have inherited systems where every step was through mud, and I have argued for rewrites I am glad nobody approved. The loan framing is the only one that has consistently led to good decisions.
Technical debt really does work like a loan, and the comparison deserves to be taken seriously. When a team takes a shortcut to ship faster, it borrows time. The interest is the extra effort every future change costs because the shortcut is in the way. So far, the standard metaphor.
The part people miss is where interest is charged. You pay interest only on code you touch. A messy module that nobody has opened in three years is an interest-free loan. Rewriting it is paying off a debt that costs you nothing, with money you could spend on debts that are bleeding you weekly.
Same system, two repayment policies. The gap between the lines is the interest.
The dangerous debt sits on the hot paths. At that client it was the pricing module. It changed almost every week, because pricing is where the business competes, and it was also the roughest part of the codebase. A change that should take two days took two weeks, every time, and each of those weeks was interest.
So the question is never how much debt do we have. It is where change frequency and roughness overlap. Plotting the two takes an afternoon with the version history and produces a map most teams have never seen.
One afternoon with the version history tells you which quadrant every module is in.
The top left corner, code that changes weekly and is in rough shape, is where repayment pays back immediately. The bottom left, rough but rarely touched, is where the rewriting instinct wants to go and where it is wasted. Engineers hate this, and I understand it. Ugly code offends. But offense is not interest.
What does a sensible repayment policy look like in practice? Three habits cover most of it.
Budget repayment inside normal work, not beside it. We reserve roughly a fifth of capacity for improving whatever code the current feature passes through. Separate cleanup sprints sound tidy and get cancelled the moment a deadline appears. Repayment that lives inside feature work cannot be cancelled without cancelling the feature.
Follow the campsite rule on hot files. Whoever touches a frequently changed module leaves it slightly better: one clarified name, one extracted function, one test that pins the behaviour down. On a file you touch weekly, small improvements compound faster than any grand refactoring plan.
Keep a debt register, one page, in plain language. When you knowingly take a shortcut before a deadline, write down what was borrowed and what it will cost to fix. Borrowing is fine. Forgetting that you borrowed is how systems rot.
And when is the full rewrite actually right? Three cases, in my experience. The platform is dead, meaning the language or framework is unsupported and hiring for it is hopeless. Nobody left in the company can change the system safely. Or the business has changed so much that the core model is wrong, not just messy. Even then, the sane path is to strangle the old system piece by piece behind a stable interface, not to stop the world for a two-year rebuild.
Rewrites fail for the same reason the debt accumulated. The habits that produced the mess move into the new codebase on day one, with the added handicap that the new code has to catch up on ten years of edge cases the old code already learned.
The client with the pricing module did not rewrite. We spent two quarters cleaning the 15 percent that actually changed and left the rest alone. Lead time for a typical pricing change went from two weeks to three days. The ugly 85 percent is still ugly. Nobody cares.
Debt is a tool. Companies do not get into trouble by borrowing. They get into trouble by not knowing what they borrowed and at what interest, and by paying down the loans that cost nothing while the expensive ones compound.
Questions I hear about technical debt
What is technical debt in simple terms?
Shortcuts in software that were taken to ship faster. Like a loan, they give you speed now and charge interest later: every change that passes through the shortcut takes longer than it should. The debt itself is not bad. Unmanaged interest is.
Which technical debt should be fixed first?
The debt in code that changes most often. Interest is only charged when code is touched, so rough modules on your hot paths cost you weekly, while rough modules nobody opens cost nothing. Version history shows you exactly where the overlap is.
How much development capacity should go into paying down technical debt?
Around 15 to 20 percent, spent inside normal feature work on the code the feature touches. Dedicated cleanup sprints tend to be cancelled under deadline pressure, so repayment should be part of everyday delivery rather than a separate project.
When is a full rewrite justified?
When the platform is dead and hiring for it is hopeless, when nobody can change the system safely anymore, or when the business has outgrown the system's core design. Even then, replace it piece by piece behind a stable interface instead of a big-bang rebuild.
.png)




