Skip to content
Technology19 November 2025 · By the Intense Path Editorial Team

Technical Debt You Should Keep, and Debt You Should Pay Now

Technical debt management fails when every shortcut is treated the same. Some debt sits still and costs nothing for years. Some compounds weekly. Only the second kind deserves a sprint.

On This Page
Pass It On

Found this useful? Send it to someone who’s building.

Technical Debt Management: Keep, Pay or Ignore | Intense Path

A team asks for four weeks to pay down technical debt. The list has nineteen items on it. Three of those items are costing money every week. The other sixteen have cost nothing for two years and will happily cost nothing for two more. Approving all nineteen is wasteful and approving none of them is negligent, and the argument that follows is usually settled by whoever is most senior in the room rather than by anything resembling a price.

The metaphor is doing real work and most teams throw away the useful half. Debt has an interest rate. Some of what gets filed under this heading compounds every week it is left alone. Some of it sits in a corner charging nothing whatsoever. Technical debt management is mostly the practice of telling those two apart, which makes it a pricing exercise before it is an engineering one.

There is also a category on that list of nineteen which is not debt at all, and mixing it in is how the list got so long. So: first separate debt from decay, then apply an interest-rate model you can run in an afternoon, then look at the specific debt that blocks hiring, which is the kind most often missed because nobody notices it until they are already recruiting.

Debt and decay are not the same thing

Deliberate debt is a decision. Somebody chose the faster path knowingly, for a reason that was sound at the time: a launch date, an unproven assumption, a market window that was open for six weeks. Decay is what happens when nobody decides anything at all.

Deliberate debt has an author

It leaves a trace: a comment, a ticket, a decision record, a paragraph in a discovery document. You can find the person who made the trade and ask whether the reason still holds. Roughly half the time it does not, and the repayment turns out to be cheap, because the reason for borrowing also described the shape of the thing that would pay it back. That is what borrowing well looks like.

Decay has nobody

A dependency three versions behind because nobody was watching. A service running on a runtime version that was never chosen, only inherited. A configuration file carrying settings from a business you stopped being. There is no author, no reason and no repayment plan, and it is worse than debt in one specific way: it is invisible to exactly the people who could authorise fixing it, and it accelerates while it is invisible.

The short version: debt was borrowed and decay was left out in the rain. You negotiate with the first and you simply clean up the second. Only one of them belongs in a prioritisation conversation, and putting decay on the same list as debt is how genuine trade-offs end up buried under housekeeping.

Interest is the only number that matters

Ask one question of every item on the list. Does this get more expensive if we leave it alone for six months? Not "is it ugly", not "would a good engineer have done it differently". Only that. The answer sorts the list faster than any scoring framework, and it is a question a non-engineer can follow, which matters when the budget lives elsewhere.

What compounds

Anything sitting on a path that other work has to cross. Data models come first, because every feature built on the wrong noun adds a workaround, and the workarounds start referencing each other. We have written about choosing a database you will not regret for the same reason: the schema is the decision with the longest tail. After that come authentication, the build and deploy path, and anything with a clock attached, such as a dependency carrying a published vulnerability. Last on the compounding list, and easy to overlook, is anything untested that people are frightened of. Fear slows every change made anywhere near it, and that is interest even though nothing in the codebase changed.

What sits still

An ugly module nobody has opened in a year. A slow administrative screen used twice a month by two people who have made peace with it. Duplicated logic inside a feature-frozen service. Naming that offends somebody’s sense of order. These charge nothing at all, and they will keep charging nothing right up until the roadmap sends somebody into that file.

The debtInterest rateWhat it actually costs you
A schema that models the wrong nounHigh, compoundingEvery new feature adds a workaround, and the workarounds start depending on each other
A dependency several major versions behindHigh, and acceleratingSecurity fixes stop arriving and the upgrade path lengthens every quarter
A deploy process one person can performHigh, compoundingEvery holiday becomes a release freeze and every incident waits for one phone
No tests around the payment pathHigh, compoundingFear, which slows every change made anywhere near it
A hand-rolled authentication layerModerate to highEvery new surface repeats the same review, and the review is never routine
An unfashionable framework, still maintainedNear zeroAlmost nothing, unless it is also abandoned upstream
Duplicated code in a frozen moduleZero until someone edits itNothing, until that module returns to the roadmap
A slow screen used twice a monthZeroIrritation, on two days out of thirty
The rate changes without the code changing

A zero-interest module becomes high-interest the day a roadmap item lands on top of it. That is why re-pricing debt belongs to roadmap planning rather than to a quarterly cleanup ritual. When the plan changes, the list changes, and items that were correctly ignored for two years may become the most expensive thing you own overnight.

The debt that quietly blocks hiring

The most expensive debt on many teams has no code smell at all, because it is not in the code. It is the part of the system that exists only in somebody’s memory. The deploy that works if you run the steps in the right order. The test suite that passes on one laptop. The environment setup that takes three days and a series of conversations. None of that shows up in a static analysis report, and all of it is charged to you at the worst possible moment, which is when you grow.

There is one measurement worth taking. How long from a new engineer’s first day to their first change reaching production without supervision? If that number is measured in weeks, you are not slow at onboarding, you are carrying undocumented debt and paying it in salary. The mechanics of fixing it are the subject of handing a codebase to someone who was not there, and the fix is almost always writing down what one person knows rather than rewriting what they built.

The most expensive debt on most teams is not in the code. It is the part of the system that exists only in somebody’s memory, and it leaves the building when they do.

There is a business framing that helps when this reaches a board. Nobody buys a refactor. What they are buying is the ability to say yes to the next thing quickly and to keep the promises already made, which is the argument in what a company actually sells. Framed as delivery speed and reliability, the request stops competing with features, because it is a property of the delivery itself.

Debt worth keeping on the books

This is the part engineers dislike and it is the part that funds everything else. Some debt should be kept deliberately, written down, and left alone.

  • The unfashionable framework that still ships. If it is maintained upstream, patched, and people are still available to work in it, its interest rate is close to zero. Fashion is not interest.
  • Duplication before the third occurrence. Two similar functions are usually just two functions. An abstraction drawn from two examples is wrong more often than the duplication was expensive.
  • A manual step that runs monthly and takes ten minutes. Automating it costs a day and creates something new to maintain. Automate it when it runs weekly, or when only one person can do it.
  • A documented, contained hack. A workaround with a comment naming the constraint and the reversal condition is a decision, not a defect. Leave it, and delete it when the constraint dies.
  • A monolith that is not hurting anybody. Splitting one deployable into eight is not paying debt. It is taking out a much larger loan, denominated in operational complexity.

The common thread is containment. Debt you can draw a boundary around, describe in a sentence and hire for is debt you can carry indefinitely. That is also the case for choosing boring technology deliberately: a tool with a large pool of people who already know it converts what would otherwise be debt into an ordinary maintenance cost, and it does so without a single line of refactoring.

How to price one item in ten minutes

Do this per item rather than per list. It takes about ten minutes each and it turns an argument about taste into a set of comparable numbers.

  1. Name the symptom, not the smell. What goes wrong, to whom, and how often. "This module is messy" is not a symptom. "Every pricing change takes two people and a manual check" is.
  2. Count how many times the next two quarters of roadmap cross it. Read that off the plan, not off memory, because memory over-weights whatever annoyed somebody last week.
  3. Decide whether it gets more expensive untouched. Security clocks and data models do. Naming conventions do not.
  4. Estimate the repayment in the same units you use for features, and state plainly that the estimate is less reliable than a feature estimate, because it is.
  5. Write the reversal condition: the fact that would make this not worth doing. If you cannot write one, you have a preference rather than a finding.
  6. Give it a severity and a priority separately, and expect them to disagree. Severity is how bad it is. Priority is when you will act, and the roadmap decides that.

That last step is the one teams collapse, and collapsing it produces a backlog where everything is urgent and therefore nothing is. Keeping the two apart is also what makes a finding legible to somebody outside engineering. It is the shape Prooflin resolves findings into: a severity, a priority and a recommendation inside a reviewable report, rather than a list of observations with no verdict attached.

The refactor that is really a rewrite

Watch for the proposal that changes the data model, the framework and the deployment at the same time. That is a rewrite wearing a refactor’s clothes, and it is usually presented as a refactor because refactors do not need approval. Name it accurately, price it accurately, and take it to whoever owns the budget. A rewrite proposed honestly is sometimes approved. A rewrite discovered halfway through never is.

The concession, and it is a genuine one: sometimes the rewrite is correct. The condition we would apply is arithmetic rather than aesthetic. When the cost of delivering the next three planned features on the current system exceeds the cost of replacing it, and you can describe how both systems run side by side for a quarter, the rewrite is the cheaper option and pretending otherwise is its own kind of debt. This is exactly the territory where a technical discovery earns its cost, because it produces the numbers instead of the opinions.

The side-by-side test

If you cannot describe, concretely, how the old system and the new one both serve live traffic for a quarter, you do not have a migration. You have a hard cutover, and hard cutovers are how teams lose a year. Write the side-by-side plan before the first line of the replacement, or accept that the date you are quoting is a guess.

What we would pay this quarter regardless

Four things come off the list first, whatever else is competing for the time. Dependencies carrying published vulnerabilities come first, because that clock runs whether or not anyone is watching it, and the fix is usually version numbers rather than design. Anything only one person can do comes second: not because that person is a risk, but because a single point of knowledge turns every ordinary absence into an incident.

Third is the build and deploy path, because a release you cannot reproduce is a release you cannot roll back, and every other item on the list becomes harder to fix once shipping is frightening. Fourth is any data model error that features are already working around, since each additional workaround raises the price of the eventual correction. Those four are ordinary application work rather than a special initiative, and they belong inside normal delivery.

Everything else stays on a register with an owner, a one-line description and a date to re-price it. A register is not a backlog. Nothing on it is promised, which is precisely why people are willing to write honest things on it, and why we would rather run product improvement against a short register of priced items than against a long backlog nobody believes in.

Where we would start on Monday

The rule, in one line: pay the debt that sits on the path of the next two quarters, plus everything with a clock attached, and deliberately keep the rest. Write down what you kept and why. A team that can name the debt it is choosing to carry is in a different position from a team that simply has not looked, even when the two codebases are identical.

The condition that reverses this advice: a system where the compounding items outnumber the still ones. At that point you are not managing debt, you are managing decay, and the honest response is to stop prioritising and work through the dependency and deploy items until the ratio changes. Prioritisation is a tool for choosing between good options. It does nothing useful when every option is already overdue.

The first step is smaller than it sounds. Take the list you already have, delete every item nobody can attach a symptom to, and price what survives with the six questions above. It usually takes an afternoon and it usually halves the list, which is the same reason a discovery step sits at the front of how we work. If the list is longer than the team and nobody agrees what is urgent, send it to us and we will start by pricing it rather than by proposing a rewrite.

Take these with you
Ask one question of every item: does this get more expensive if we leave it for six months? That single test sorts a debt list faster than any scoring framework.
Deliberate debt has an author and a reason you can revisit; decay has neither, is invisible to the people who could authorise a fix, and accelerates while it stays invisible.
The costliest debt on most teams is undocumented knowledge, and the measurement that exposes it is how long a new engineer takes to ship unsupervised.
Unfashionable but maintained tools, duplication before the third occurrence and contained documented hacks are all worth keeping, provided you write down that you chose to keep them.
A proposal that changes the data model, the framework and the deployment together is a rewrite, and it deserves a budget conversation rather than a refactor ticket.

Common questions.

What is the difference between technical debt and bad code?

Technical debt is a trade made knowingly, usually to reach a date or test an assumption, with a reason that can be revisited later. Bad code is simply work done poorly, with no trade behind it. The practical difference is that debt has an author who can tell you whether the original reason still applies, which often makes repayment far cheaper than it first appears.

How much time should a team spend on technical debt?

A fixed percentage is the wrong instrument, because it funds low-interest work in quiet quarters and starves urgent work in busy ones. Tie the spend to the roadmap instead: pay whatever sits on the path of the next two quarters of planned work, plus anything carrying a security clock. In practice that varies considerably between quarters, and it should be allowed to.

Is it ever right to leave technical debt alone permanently?

Yes, when the debt is contained, documented and has no interest rate. Duplicated logic in a module nobody edits, a slow screen used twice a month, or an unfashionable framework that is still maintained can all be carried indefinitely. The requirement is that the decision is recorded with an owner and a date to re-price it, so it stays a choice rather than becoming an oversight.

How do I explain technical debt to non-technical stakeholders?

Describe the symptom and its cost, never the code. "Every pricing change takes two people and a manual check" lands where "the module is poorly structured" does not. Then attach it to something already promised: the feature it will slow down, the release it puts at risk, the hire it makes expensive. Debt competes with features until it is framed as delivery speed.

When should a refactor become a rewrite?

When delivering the next three planned features on the current system costs more than replacing it, and when you can describe how both systems serve live traffic side by side for a quarter. If that side-by-side period cannot be described concretely, you are planning a hard cutover rather than a migration, and hard cutovers routinely consume far more time than the estimate allowed for.

Does technical debt affect hiring?

Directly, and in two ways. Undocumented processes and one-laptop environments mean a new engineer takes weeks rather than days to ship anything, which is salary spent on waiting. Separately, a stack that is both unfashionable and abandoned upstream shrinks the pool of people who will consider the role. A maintained but unfashionable stack does not cause the same problem.

Facing this in your
own business?

Tell us where you’re headed — we’ll map the shortest honest route.

Start a Project