A company orders a change that took three days two years ago. Today the vendor quotes two weeks for it, and the proposal now includes a line about "a necessary intervention in the core of the system". On the surface nothing has changed — the same system, the same type of change, often the same team. The only thing that changed is how many old decisions someone has to work around before reaching the place where a single button is supposed to go.
That is exactly what technical debt is. It is not an insult aimed at developers, nor proof that someone did a bad job. It is the gap between how the software is built today and how it would need to be built for people to work in it comfortably tomorrow. That gap appears entirely naturally — the business changes, requirements change, libraries and platforms shift underneath you. The problem starts only when nobody keeps a record of it and its interest is paid quietly, in the form of ever longer estimates and ever more cautious developers.
Deliberate debt versus rot
The most useful distinction a non-technical owner can adopt is between debt somebody deliberately took on and debt that never decided to come into existence.
Deliberate debt is a legitimate business decision. You need to make the season, so the price list gets hard-coded for three months instead of becoming a configurable module. A pilot for a single customer runs on a manual export instead of an integration, because you have no idea whether the pilot will survive. These are the right decisions — provided they meet three conditions: it is written down, it has an owner, and it has a due date. Without those three things it is not a loan, it is just a postponement that everyone forgets.
Accidental rot is what nobody decided. It grows out of people leaving, persistent copy-paste, libraries nobody has updated in three years, tests that stopped being written when the pressure was on and never started again. This type of debt is more dangerous because it leaves no trace — there is no meeting note anywhere saying "we are knowingly doing it this way".
Symptoms you can see without reading any code
You do not need to understand the architecture to know you have a problem. Technical debt shows up in numbers and in people's behaviour, both of which are right in front of you.
Estimates grow for comparable tasks. Not for new and more complex things — that is normal. But if "add a field to the form" cost two days last year and costs a week today, you are paying interest.
There is a module everyone is afraid of. You recognise it by how the team talks about it: "I would rather not go into invoicing", "that has to be done over the weekend". Fear of touching something is the most reliable indicator you have.
Something different breaks after every release. If a fix in orders breaks reporting, the system has no boundaries between its parts and no safety net. That safety net is called automated testing, and it is worth addressing before you start counting the damage — more on that in the piece on automated software testing and why it pays off.
Onboarding a new developer takes disproportionately long. If a new person reaches their first independent task only after months, the system is either undocumented or inconsistent — most often both.
One person knows everything that matters. When the answer to "who understands this?" is always the same name, you do not have a vendor, you have a single person plus a risk.
| Symptom | What it usually means | How to record it |
|---|---|---|
| Growing estimates for similar tasks | Tangled dependencies, missing abstraction | Compare estimate against reality for 5 similar tasks over the last 2 years |
| Fear of a specific module | Missing tests or unknown original intent | Have the team mark modules with a traffic light (green/amber/red) |
| Regressions after releases | Insufficient test coverage, tightly coupled code | Count hotfixes within 7 days of a release |
| Long onboarding | Missing documentation, inconsistent patterns | Measure time to the first independently delivered task |
| Dependency on one person | Know-how never transferred | List of areas with a single expert |
How to make the debt visible and prioritise it
Technical debt that is written down nowhere does not exist for anyone except the developers — and they will hide it inside the estimate. The first step is therefore a debt register: a plain table where every item has four columns — what it concerns, what it blocks or endangers in the business, what happens if we do nothing, and an estimate of the cost of removing it.
The second step is prioritisation. And this is where most companies make the same mistake: they leave the order to the developers. A developer naturally wants to fix what irritates them most. That need not be what costs the company most.
A practical criterion has three axes:
- Change frequency. Debt in a module that changes every month generates interest. Debt in a module nobody has opened for three years generates almost none.
- Exposure. What sits behind that module — revenue, personal data, a legal obligation? Debt in authentication or payment processing carries a different weight than debt in an internal export for marketing.
- Cost of delay. Some debt is stable and can wait. Other debt grows — unmaintained dependencies reaching end of support, or a platform that becomes far more expensive to migrate away from later.
Technical debt never repays itself. Either you repay it deliberately and on budget, or every future estimate repays it for you — it is simply called something else.
Repayment strategies and their risk profiles
In practice there are four realistic ways to reduce debt. The first two can be combined; the last two are decisions you make once and reverse with difficulty.
| Approach | How it works | When it makes sense | Main risk |
|---|---|---|---|
| Continuous refactoring | Every change leaves the part it touched in better shape than it found it | The system is actively evolving, the team is stable | Without rules it evaporates under deadline pressure |
| Reserved capacity percentage | A fixed share of capacity (typically 10–20%) goes to the debt register | The debt is already visible and needs systematic reduction | Requires discipline and reporting, otherwise the percentage gets "borrowed" for features |
| Gradual module-by-module replacement | A new implementation runs alongside the old one, traffic moves across in pieces | An outdated platform but sound business logic | Temporary dual running, higher integration demands |
| Full rewrite | A new system is built from scratch and replaces the old one at once | The system genuinely cannot be evolved or operated | The highest — a long period with no delivered value and the loss of unwritten rules |
Why a rewrite is usually the worst option
A rewrite looks attractive because it promises a clean start. In reality it has three systematic problems.
First: the old system contains years of undocumented decisions. Those odd exceptions in the discount calculation that nobody can explain are usually responses to real situations. A rewrite silently discards them and you rediscover them in production.
Second: during a rewrite the company pays for two teams — one maintaining the old system, one building the new one — and receives no new functionality for many months. That is precisely the period in which a competitor ships something.
Third: the new system starts generating its own debt from month one. If the way of working that created the debt has not changed, you will be in the same place in three years. That is why it is often more valuable to change the delivery process and the approach to software maintenance and evolution after launch than to change the technology itself.
You can defend a rewrite when the platform has lost support, when you cannot find people for it, or when the business model has changed so much that the original data model no longer makes sense. Even then, gradual module-by-module replacement is usually safer than swapping everything at once.
How to talk about it with your vendor
Technical debt is a good topic on which to test the quality of a vendor. A good vendor names it themselves, in terms of business consequences. A weak one either hides it or uses it to explain away every inflated estimate. If you are currently choosing a partner, it is worth working through the checklist for choosing a software vendor and adding the points below to it.
Several concrete things belong in the contract or in the framework of cooperation:
- A definition of done. A task is done when it has tests and documentation, not when "it works for the demo".
- Reserved capacity for debt. An explicitly agreed monthly percentage of capacity, with a report on what was done with it.
- Dependency updates as part of maintenance. Not as a separately invoiced project once every three years.
- A regular status report. Quarterly, in the language of risk: what got worse, what was repaid, what is looming.
- Ownership of code and access. Including the repository, documentation and infrastructure access on your side.
- A handover clause. A description of what you receive if you end the cooperation — the cheapest insurance against lock-in there is.
At INTERFASE we prefer to settle these points at the start of a cooperation rather than at the first conflict; details of our approach to custom software development are in a separate section.
When not to address the debt
Not every debt is worth repaying. If the system is being switched off within a year, if the module supports a product with no proven demand yet, or if it is a piece of code that changes once every two years — leave it alone. Repaying debt only makes sense where you are paying interest. Money put into cleaning up a dead part of the system is lost just as reliably as money put into neglecting it further.
Summary
Technical debt is an economic quantity, not a technical complaint. Deliberate, time-boxed debt is a normal management tool; the dangerous kind is the debt nobody records. As an owner you recognise it by growing estimates, regressions after releases, onboarding length and fear of specific modules — all of which you can measure without reading code.
Prioritise by change frequency, exposure and cost of delay, not by what irritates the team most. Repay continuously or through a reserved percentage of capacity, keep a rewrite as the last resort, and even then prefer gradual module-by-module replacement. Above all: agree on how debt will be reported before it starts to hurt.
If you need an independent view of the state of your system and an estimate of which parts of the debt are genuinely worth repaying, get in touch and we will go through it together.