Technical debt is not about ugly code — it is about decisions nobody revisits
The myth of ugly code
When someone opens an old file and winces, it is common to hear "this is technical debt." Almost always, it is not. Ugly code that works, that nobody needs to touch, and that breaks nothing is just ugly code — harmless, if uncomfortable to look at.
Real technical debt is something else: a decision made consciously (or not) under a constraint of time, knowledge, or scope, that accrues interest as the system grows on top of it. The comparison to financial debt is literal — you took a shortcut to ship faster, and that shortcut charges installments until it is paid off.
Where real debt comes from
In practice, technical debt is born in three places:
- Deliberate and informed. The team knew there was a better way, weighed the deadline, and consciously chose the shortcut — usually to validate something before investing in the right version.
- Accidental. Nobody noticed the problem at the time. It only became visible once the system grew and the original decision stopped making sense.
- Inherited. The current team was not even there when the decision was made. They received the interest without signing the contract.
The common mistake is treating all three the same way. Deliberate debt has an owner and a deadline — it should be documented, with a date to revisit it. Accidental and inherited debt require investigation before any fix, because nobody is quite sure why things are the way they are.
How to pay it off without stopping the product
Nobody convinces leadership to stop for six weeks to "refactor everything" — and they should not, because that is rarely the real problem. What works is treating debt like any other priority item, with a simple test:
- Is it on the path of some future delivery? If so, paying now is cheaper than paying after building more on top of it.
- Is it causing a recurring incident? A bug that keeps coming back is a sign the debt is already charging compound interest.
- Does anyone understand why it exists? If the answer is no, the first step is not to rewrite it — it is to investigate before destroying context that might matter.
Debt that meets none of these three criteria can wait. And that is fine — not every debt needs to be paid off; some will never charge enough interest to justify the effort.
The habit that prevents the snowball
What separates teams that live putting out fires from teams that evolve predictably is not talent — it is a simple habit: recording the debt the moment it is created, with one line on why. A comment, a board item, a line in a document — the format does not matter, what matters is that the decision stays visible for whoever comes next.
Technical debt is not an engineering embarrassment. It is part of building something fast enough to exist in the real world. The problem was never taking it on — it was forgetting it exists.
Related posts
Hiding the menu is not access control: how I built modules each customer can switch on and off
A small shop does not want to see commissions, invoicing and a customer portal on day one....
A webhook is not a source of truth: what I learned integrating electronic tax invoices
Tax invoices are processed in the background: you issue one, get 'processing' back, and th...
My second SaaS started from the code of the first: what I could reuse and what I had to rewrite
Oficina Simples was born as a fork of Estoque Simples. Login, plans, billing, privacy comp...