I’m tired of the phrase “technical debt.”
Not the concept. The concept is real and useful. I’m tired of how it’s used. Every codebase I inherit, every new codebase I inherit, someone pulls me aside and says “we have a lot of technical debt.” What they mean is: there’s code they don’t like. There are decisions they didn’t make. There’s a system that was designed for a different stage of the company.
That’s not debt. That’s software aging. And calling everything “debt” makes it impossible to prioritize the things that actually need fixing.
What technical debt actually is
Ward Cunningham’s original metaphor was specific. Debt is a deliberate shortcut you take to ship faster, with the understanding that you’ll pay it back later. You know the right approach. You choose the expedient one. You accept the interest cost.
That’s useful framing. It implies intent and a plan to repay.
What most people call “tech debt” is something else entirely:
- Code written by someone who left, in a style nobody likes anymore
- An architecture that was right for 10 users but not for 10,000
- A framework choice that fell out of fashion
- A service that works but is hard to understand
- An API that’s ugly but functional
None of that’s debt in the Cunningham sense. It’s just… code that aged. Software entropy. The natural consequence of building something over years with changing teams, changing requirements, and changing fashions.
The distinction matters because debt implies you should pay it back. And the honest truth is: a lot of the stuff people label as “tech debt” doesn’t need fixing. It needs acceptance.
When it actually matters
Real debt – the kind worth tracking and paying down – has measurable costs:
It causes incidents. If the same component is behind repeated production issues, that’s not aesthetic displeasure. That’s a reliability risk with a price tag.
It blocks delivery. If adding a feature to a specific area takes 3x longer than it should because of tangled dependencies or missing tests, you’re paying interest on every sprint.
It creates security risk. Outdated dependencies with known vulnerabilities. Auth systems with gaps. Unencrypted data stores. This is debt with existential consequences.
It prevents hiring from working. If new engineers can’t contribute meaningfully for months because the codebase is impenetrable, that’s a real cost.
If none of those apply, you probably don’t have a debt problem. You have a preference problem. And that’s fine. But don’t burn engineering capacity rewriting a working system because someone doesn’t like the coding style.
The “rewrite it” trap
The most expensive form of fake debt management is the rewrite. I’ve seen it at three different companies. The pitch is always the same: “The current system is unmaintainable. We need to rewrite it from scratch. It’ll take 6 months.”
It never takes 6 months. It takes 18. The new system ships with half the features of the old one. The old system keeps running in parallel because the migration is never complete. Now you have two systems to maintain.
At Decloud, we almost fell into this with our billing system. It was ugly. It was a monolith. Everyone hated working on it. But it worked. It processed payments correctly. It had years of edge cases handled.
Instead of rewriting, we strangled it. Extracted one capability at a time into new services. Kept the old system running for the parts we hadn’t migrated yet. It took longer than a rewrite would have, but we never had a period where billing was half-working.
How to actually manage it
If you have real debt – the kind that causes incidents, blocks delivery, or creates security risk – track it explicitly.
I keep a simple registry. Each entry has: what the debt is, who owns it, what the impact is, and what the decision is (fix now, fix later, accept permanently).
The key is that last field. Some debt you accept. Permanently. The system works. The cost of fixing it exceeds the cost of living with it. That’s a valid decision. Write it down and move on.
For debt you do want to fix, allocate a steady percentage of capacity. I recommend 15-20%. Not in a dedicated “debt sprint” once a quarter – that never works because it gets deprioritized. Bake it into every sprint. Every team, every sprint, some debt work alongside feature work.
Talk about it honestly
The worst thing you can do is use “tech debt” as a catch-all complaint. When everything is debt, nothing is. When you bring a list of 50 items labeled “tech debt” to a planning meeting, leadership tunes out. Reasonably.
Instead: “This component caused 3 incidents last quarter and adding the subscription feature will take 4 extra weeks because of its coupling to the payment module. Fixing the coupling first saves net time and reduces incident risk.”
That’s a business case. That gets funded.
“The auth service is old and ugly” isn’t a business case. If it works, it works. Spend your credibility on the things that actually hurt.