Software Strategy7 min read
When Does Technical Debt Become a Business Problem?
Not all old code is debt. It matters once it measurably slows delivery, raises defects, or concentrates knowledge in one person.
Norvane Team
Technical debt is among the most used and least agreed-upon terms passing between engineering and the rest of a business.
On the engineering side it usually describes a discomfort: the code is old, the structure is tangled, changing it is unpleasant. On the business side it often lands as a request to postpone something — not now, we'll look at it later.
Both readings can be fair, because the two sides are using one word for different things. Making the term useful means taking the metaphor literally: debt is the thing you pay interest on.
If it isn't charging interest, it isn't debt
Age alone does not make something debt. A ten-year-old module that nobody touches, that works, and that does not need to change is not technical debt. It may be ugly. It costs nothing.
Debt is what you pay repeatedly. If every new feature that touches an area burns extra days, if each change breaks something unexpected elsewhere, or if only one person can safely modify it, interest is accruing.
That distinction changes a great deal in practice. "The code quality is poor" is an aesthetic judgement and cannot be prioritised. "Every piece of work touching this module takes twice as long" is measurable and can be budgeted.
So the useful question is not whether you have debt — every system does. It is where you are paying interest, and how much.
The four places interest shows up
Technical debt is spotted by watching how a team behaves rather than by reading code. It generally surfaces in one of four ways.
Delivery time. When work of similar size takes progressively longer, the difference is interest. The team has not slowed down; it is clearing more obstacles to do the same job. The visible symptom is estimates being overrun consistently, and "it looked simple" becoming a recurring phrase.
Defect rate and reopened work. A fix that breaks something else indicates parts of the system are more tightly coupled than anyone intended. The same bug returning in a different form is the same signal.
Dependence on individuals. When only one person can touch certain areas, that is an operational risk rather than a technical one. A workflow that stops while someone is on leave is debt regardless of how the code reads.
Time to a new joiner's first contribution. If it takes weeks for someone new to make their first meaningful change, the system is not explaining itself. That measure is easy to collect and easy to compare over time.
All four are things a non-technical manager can track. In practice, this is the most reliable way to get technical debt into a budget conversation at all.
How the debt was created is worth tracking too. Some of it is deliberate: a temporary solution chosen to make a date, understood to be temporary. That is a healthy trade — as long as it is recorded. Without a record, the same solution is treated as permanent within a few months and things get built on top of it. The rest accumulates without anyone noticing; no wrong decision was made, it is simply that nobody looked at what the system had become for a long time.
Not all debt should be repaid
Clearing every debt is not a goal. Some is carried deliberately, and that is often the right call.
What decides it is whether the debt sits on the path of upcoming work. A tangle in an area nobody will touch for six months generates no interest; fixing it is a matter of taste. A tangle in a module that the next three projects all run through gets paid for every time.
The practical approach is to lay debt over the roadmap. If the next pieces of work are known, so is which debt stands in their way — and prioritisation stops being an abstract argument about "improvements."
Risk is the second criterion. A dependency no longer receiving security updates, a data layer whose backups have never been tested, or a deployment process only one person understands should be handled independently of interest, because their cost does not arrive gradually. It arrives all at once.
Maintenance debt and structural debt
Two quite different things get filed under the same heading, and confusing them sends budget to the wrong work.
Structural debt concerns how the system was built: responsibilities split along the wrong lines, modules bound too tightly to one another, a model that does not represent the data honestly. Fixing it requires design decisions and is usually expensive.
Maintenance debt comes from neglect: dependencies left un-upgraded, runtime versions falling behind, configuration nobody has revisited in years. None of it results from bad design. It simply was not done.
The important difference between them is the shape of the cost. Structural debt costs linearly — a little extra time on every touch. Maintenance debt accumulates quietly and then arrives as a step change.
Version upgrades are the clearest example. Updating a dependency as each release appears is small and routine. Being three major versions behind is a project, because every breaking change in between now has to be absorbed at once. The same work became expensive purely by being deferred.
The practical conclusion is that maintenance debt should not be a prioritisation question at all. Done regularly and in small pieces, it never becomes a budget line. Structural debt genuinely should be prioritised, because it does not always need fixing.
When a team asks for time to address technical debt, the first useful question is usually which of the two they mean.
The rewrite fallacy
Past a certain point, the most attractive proposal is to start again from nothing. That proposal underestimates three things at once.
The first is the invisible knowledge in the existing system. Most of the odd conditions accumulated over the years are not arbitrary; they are the residue of real situations. A team starting fresh meets those situations again and rediscovers the same oddities — this time with customers present.
The second is duration. The product rarely stops during a rewrite, so the old system keeps needing maintenance. For a while the team carries two systems instead of one.
The third is that the new system will also produce debt. The same people, under the same pressure, will make comparable decisions. Where the problem is genuinely the code, a rewrite helps; where the problem is how decisions get made, the replacement ages faster than the original did.
What usually works better is drawing a boundary and migrating gradually: new work is built in the new structure, and old areas move only when something needs to touch them. As with deciding when a redesign is justified, what warrants starting over is foundational rather than aesthetic.
Keeping debt visible
The hardest thing about technical debt is usually not its size but its invisibility. Because nobody measures it, the argument runs on instinct.
Changing that does not require a heavy process. Having the team record the obstacles they hit as short notes, reviewing that list at the start of each quarter, and pulling in only the items sitting on the roadmap is enough for most companies.
The real gain is that debt stops being a request and becomes a line item. As a line item it can be argued for, deferred, or accepted — all three of which beat deciding by instinct.
Keeping the list short matters too. A hundred-item debt inventory becomes a document nobody opens; ten items tied to the roadmap actually get used each quarter.
Assessing technical debt
- Is this debt charging interest, or is it merely old?
- Has similar work been taking longer over time?
- Do fixes in this area break something else?
- Can only one person safely change it?
- How long does a new team member take to make a first contribution?
- Does this debt sit on the path of upcoming work?
- Is there a risk that arrives all at once: security, backups, deployment?
- Has the request been expressed as a measurable delay?
In closing
Technical debt is not evidence of poor engineering. It is the accumulation of decisions traded between speed and durability, and a good number of those decisions were right at the time.
The problem is rarely that debt exists. It is that nobody knows what it is costing. Once the interest is measured, the discussion stops being technical and becomes an ordinary conversation about priorities.
In our software consulting work, that conversation usually starts not with the code but with which pieces of work took longer than expected over the last three months, and why.