Technical debt is not a synonym for mess
The term has made quite a career and lost its meaning along the way. Today "technical debt" is often a label for anything someone doesn't like in the code — from a genuine production risk to a disagreement with somebody else's naming convention. That dilution has a real cost: if everything is debt, the business stops taking anything on the list seriously.
Let's go back to the original. Ward Cunningham, who coined the metaphor, was talking about something quite different from mess: a deliberate decision to ship an imperfect but faster solution and pay for it later. Exactly like a loan — you take it because money today is worth more than money a year from now. The key word is: deliberate.
A mess created out of ignorance is not debt. It's a mess. The difference isn't academic — it determines how you fix it and how you talk about it with the board.
Four types of debt — and only two are worth taking on
The most useful model splits debt along two axes: did you take it on deliberately, and was it a prudent decision?
Deliberate and prudent — "we know it's a workaround, we're shipping before the regulatory deadline, we'll come back to it in Q3". This is debt in the original sense. It's fine, as long as someone has recorded where it was taken on and when it will be repaid.
Deliberate and reckless — "we don't have time for design, let's just write it". A conscious decision, but with no repayment plan. This debt has no maturity date, so it grows indefinitely.
Inadvertent and prudent — "now, a year on, we know how we should have done it". The natural result of learning about the domain. It can't be avoided and there's no point apologising for it; you just need to record it and fix it when the opportunity arises.
Inadvertent and reckless — "what's a design pattern?". This isn't debt, it's a lack of competence. A refactor won't fix it, because the problem will reappear in the next module. You fix it with mentoring, code review and process — not with a clean-up sprint.
The practical takeaway: before you plan repayment, establish which type you're dealing with. The first three are solved technically. The fourth — only through people.
When debt pays off
A team that never takes on technical debt usually delivers too slowly. There are situations in which a deliberate shortcut is simply a good business decision:
- Validating a hypothesis. You're building a feature without knowing whether anyone will use it. A polished architecture for something that may be removed next month is wasted time. The same logic underpins what should go into an MVP — and what doesn't need to be there.
- A hard external deadline. A regulatory requirement, a sales season, a contract with a client. Entering the market with a workaround is often vastly better than entering a month later with an elegant solution.
- Code with a short expected lifespan. A one-off migration, a campaign, an integration with a system that will be switched off in six months. Investing in the quality of code that will disappear on its own never pays back.
- An area with low volatility. A module nobody has touched in two years and has no reason to touch. Ugly, but it works — the interest here is close to zero.
In each of these cases debt is fine on one condition: it's written down. A code comment linking to a ticket, a backlog item, a note in an architecture decision record. Undocumented debt stops being a decision after six months and becomes a mystery.
When debt has to be repaid — and how to measure it
The interest on technical debt can be counted. That's not a metaphor — these are concrete numbers you usually already have in your tools.
Lead time for similar tasks is growing. The clearest signal. If a feature comparable to one from a year ago now takes twice as long, you're paying interest. Compare tasks from the same category, not sprint averages.
The number of regressions per release is rising. A fix in one place breaks something elsewhere — the very definition of overly tight coupling between modules. The metric: how many post-release bugs affect areas the release didn't formally touch.
The time from merge to production is getting longer. Manual steps, flaky tests, fear of deploying on a Friday. This is debt in the process, not the code — usually the cheapest to repay and the most rewarding.
Onboarding a new developer takes months. If the first independent task is only possible after eight weeks, you pay the cost of the debt with every hire.
The share of sprint time spent on "maintenance" is growing. Once it exceeds roughly half, the team is no longer really developing the product — it's just keeping it running. That's the point at which the conversation stops being about refactoring and starts being about reactivating the project.
We described the symptoms as they look from the outside in 5 signs your mobile app is quietly dying.
A separate category that is non-negotiable: security and compliance debt. Vulnerable dependencies, secrets in the repository, missing support for regulatory requirements. There's no discussion about priority here — there's a deadline.
How to talk about it with the business
The most common reason debt doesn't get repaid isn't technical. It's about communication: the team asks for "time to refactor", and the decision-maker hears "we want a quarter to shuffle code around with nothing a customer will ever see".
Four things that change that conversation:
Talk about the effect, not the solution. Not "we need to refactor the orders module", but "every change to orders costs us three days instead of one and causes a bug in every fourth release; once it's cleaned up, it'll be back to one day".
Give a number and a payback period. "Two weeks of work, paying for itself in about four months at the current rate of change in this module." Even a rough number moves the conversation from a matter of faith to a matter of investment.
Show what happens if we do nothing. Not as a threat, but as a projection: in six months delivering feature X will take this long, the risk of failure in area Y is growing, bringing a new person onto the team costs this much.
Tie repayment to a business goal. The most effective moment to clean up the payments module is the sprint in which a new payment method is being added anyway. Refactoring "along the way" is cheaper and doesn't need separate approval.
Sometimes the arguments aren't enough, because they come from the team, which is a party to the matter. That's when an independent outside assessment helps — an audit gives you exactly that: a list of priorities nobody in the company has to defend with their own reputation.
Four repayment strategies (and one that doesn't work)
The Boy Scout rule — leave the code cleaner than you found it. Every task tidies up the immediate surroundings of the change. It costs nothing, needs no approval and works indefinitely. The limitation: it won't touch architectural problems, and it requires discipline in code review.
A fixed budget in every sprint. 15–20% of the team's capacity goes to debt, planned like any other work. It works best in teams with a stable pace. The condition for success: the budget has to be the default, not something negotiated sprint by sprint — otherwise it gets eaten up by the first urgent issue.
Repayment alongside features. Cleaning up a module becomes part of the scope of a business task that touches it anyway. The best effort-to-impact ratio, because you fix what is actually changing — in other words, what is actually generating interest.
A dedicated remediation project. A few weeks of focused work on one area, with a goal and a metric. Justified for architectural debt that can't be broken into smaller pieces. It needs a clear scope — otherwise it dissolves into "tidying up".
And the strategy that doesn't work: "we'll do it when things calm down". Things never calm down. Debt without assigned time, an owner and a deadline isn't planned — it's postponed forever.
What not to repay
Just as important is the list of things worth deliberately leaving alone:
- Code that doesn't change. If a file hasn't been modified in two years and there's no reason for that to change, its ugliness costs nobody anything.
- Systems with a shutdown date. Tidying up something that disappears in six months is a pure loss.
- Aesthetic issues with no impact on change. Style preferences are settled by an automatic formatter, not a backlog ticket.
- Debt in an area that will be rewritten anyway. If the decision to rebuild a module has already been made, patching it in the meantime is double work — we cover the criteria for that decision in refactor or rewrite from scratch.
An audit that doesn't tell you what you don't need to do is a wish list. The same goes for a technical debt register.
Summary
Technical debt isn't a flaw in the process — it's a normal part of it, just like a loan in a growing company. It only becomes dangerous when nobody records it, nobody counts the interest and nobody has the mandate to repay it.
Three things are worth introducing regardless of project size: a register of deliberate shortcuts, a fixed repayment budget and a handful of metrics that show whether the interest is growing. That's enough to turn the debt conversation from a quarterly argument into an ordinary line item in planning.
If you'd like someone from outside to assess what the current state of your code is really costing you, and which items on this list are urgent and which can wait — we do exactly that as part of our audits and consulting, and for longer engagements also as IT team support. You can also start with our 15-point checklist or simply get in touch.