Skip to content
Home About Services Portfolio Blog Contact Get Started
Custom Software

Software Technical Debt Repayment Plan: Pay Down Debt Without Stopping Feature Work

Written by

MTD Technologies

Published
Read Time 9 min
Software technical debt repayment plan illustration showing a codebase being repaired while new features are added

Every codebase that has survived real customers carries technical debt, and that is not a confession of failure. It is the normal result of shipping under deadlines, learning what customers actually want, and changing direction as a business grows. The problem is rarely that debt exists. The problem is that nobody owns it, nobody measures it, and it is paid down in panics — a frantic rewrite here, a stalled roadmap there — instead of as a routine part of delivery. A software technical debt repayment plan fixes that. It turns debt from a vague anxiety into a visible backlog, a protected slice of capacity, and a sequence of decisions your team can defend to anyone, including a non-technical owner.

This guide is for owners, product managers, and engineering leads who need both things at once: features that keep shipping, and a codebase that does not get slower and more expensive every quarter. It covers the register, the capacity rule, and sequencing — and which kinds of debt can safely wait.

What technical debt actually is, and what it is not

The term was coined by Ward Cunningham, who compared shipping quick, imperfect code to taking on financial debt: you gain speed now, and you pay interest later in the form of slower changes. Martin Fowler’s technical debt quadrant adds a useful distinction — debt can be deliberate or inadvertent, prudent or reckless — and that distinction matters, because not all debt deserves the same response.

Deliberate, prudent debt is a decision: you knowingly ship a simpler version to hit a launch date, with a note that it will be revisited. Reckless debt is different: copy-pasted logic nobody understands, no tests around payment code, a framework version so old that security patches no longer exist. Inadvertent debt is what you discover later — the design that made sense with ten customers and breaks with ten thousand. A repayment plan treats these differently. Deliberate debt gets scheduled. Reckless debt gets stopped at the source. Inadvertent debt gets investigated before it gets fixed, because fixing the wrong thing is its own kind of waste.

Just as important is what debt is not: not every imperfection deserves fixing. Code that is ugly but stable, rarely touched, and well understood may never be worth fixing, and naming that is part of the plan.

A software technical debt repayment plan starts with a register

You cannot prioritise what you cannot see, and the first surprise in most debt exercises is how much of it lives only in developers’ heads. The register is a simple, shared list — a spreadsheet is fine, a board in your issue tracker is better — with one row per debt item and the same columns every time:

  • What it is, in one sentence — for example, “checkout totals are calculated in three places and can disagree.”
  • Where it lives — module, service, or file area, so anyone can find it.
  • Type — code, architecture, test, documentation, infrastructure, or data.
  • Interest rate — what it costs you every sprint: hours lost, bugs caused, features it blocks.
  • Risk if left alone — security, compliance, data loss, or key-person dependency.
  • Fix size — small, medium, or large, estimated honestly, not precisely.
  • Owner and date logged — so items do not drift back into invisibility.
Software technical debt repayment plan illustration of a developer sorting technical debt by priority

Populate the register in a single focused session: every developer’s top five items, what breaks repeatedly according to support and operations, and which features took surprisingly long and why. Cap the first version at thirty to fifty items — a register with three hundred rows is a new source of guilt, not a plan. Add every new piece of deliberate debt at the time it is created, and the register stays honest.

One rule makes the register work: every item needs an interest rate in business terms. “The reporting query is slow” is a complaint; “it costs two days of manual reconciliation every month-end and blocked the new pricing report twice” is a case for funding. If you cannot state an item’s cost in time, risk, or blocked revenue, it belongs at the bottom.

The 20% capacity rule: how to keep shipping while you pay down debt

The most common failure mode is the all-or-nothing response: either debt is ignored until it becomes a crisis, or all feature work stops for a “refactoring quarter” that destroys trust with the business. The capacity rule avoids both. Reserve a fixed share of each sprint — 20% is a good starting point for a codebase with meaningful debt — for register items, and protect it the way you protect any other commitment. It is not spare time to be raided when a feature slips. It is the mortgage payment.

In practice, this means debt items are sized and scheduled like features, in the same planning meeting, by the same people. A sprint might carry four feature stories and one debt item. Small debt items ride along with related feature work: if you are touching checkout anyway, you fix the duplicated totals logic as part of that story, not as a separate project. Large items get broken down until they fit the capacity slice, or they get a proper business case of their own. The percentage is adjustable, but a protected, non-zero number is non-negotiable. Without it, debt repayment is a wish, not a plan.

Software technical debt repayment plan illustration of splitting team time between new features and repairs

One exception: an actively dangerous item — an unpatched vulnerability, a data-integrity flaw, a compliance gap — does not wait for its 20% slot. It is an incident. The capacity rule is for chronic debt that otherwise never gets a hearing, not emergencies.

Sequencing: what to pay first

With a register and protected capacity, sequencing becomes a judgement call you can explain. We use four tiers, in this order:

  • Pay first: high-interest, high-risk debt. Anything that slows every feature, causes repeat incidents, or puts security, payments, or customer data at risk. A shared calculation that can disagree across the system belongs here, as does an unmaintained dependency with known vulnerabilities.
  • Pay second: friction on the roadmap. Debt that stands directly in front of features you have already committed to. If the next quarter’s work touches the reporting module, fix the reporting debt first and the features get cheaper.
  • Pay third: small wins with visible payoff. Quick items that free up developer time or remove a daily annoyance. These build trust in the process, which is what keeps the capacity rule alive.
  • Leave for now: low-interest, low-risk debt in stable code. Record it, revisit it if that code becomes active again, and do not apologise for leaving it.

Resist starting with the biggest, most satisfying rewrite: large items often deliver the least visible value per week of effort. The interest-rate column exists to stop this — a two-day fix that unblocks a whole team beats a two-month rewrite nobody outside engineering can see. When a large item does earn its place, treat it as its own project and consider the strangler approach: build alongside the old system, move traffic piece by piece, and retire old code only after the replacement has proved itself. Our legacy system migration plan guide covers that pattern, which exists because big-bang rewrites fail so reliably.

When debt is fine, and when it is not

Some debt should never be repaid, and saying so is part of the plan. Prototype code that validated an idea and will be discarded, a feature for a market you have exited, an internal tool used by three people twice a year — repaying these is pure cost with no return. Similarly, a system in maintenance mode with no roadmap does not need architectural purity; it needs stability and a dignified end of life.

Debt is not fine when it compounds. Watch for four warning signs: developer onboarding keeps getting longer, estimates inflate for the same kind of change, the same class of bug recurs, or one person alone understands a critical area. Any one of these means the interest rate is higher than admitted — move the item up the register. Key-person dependency is debt in human form, repaid with documentation, pairing, and shared ownership.

From our experience: the gotchas nobody puts in the plan

After years of this work across client codebases at MTD Technologies, a few lessons keep repeating. First, test and infrastructure debt is invisible until it bites: a slow test suite gets skipped, a manual deployment process gets feared, and both quietly tax every release — include them from day one. Second, never make debt repayment a separate team’s job while feature developers keep creating new debt, or the register grows faster than it shrinks. Third, watch for debt disguised as process: an approval chain added to work around a fragile system is not a control, it is interest paid in meetings.

Fourth, be honest about estimates. Debt items are routinely underestimated because the full extent of the mess is only visible once you start. Size them in ranges, review the register monthly, and retire items that turned out not to matter — a register that only grows is a register nobody trusts. Finally, report progress in business terms. “We closed twelve register items” means little to an owner. “Checkout changes now take half the time they took last quarter, and month-end reconciliation no longer needs manual fixes” is a reason to keep funding the 20%.

Frequently asked questions

How much team time should a software technical debt repayment plan take?

Start with 20% of sprint capacity and adjust from evidence. A healthy codebase may settle at 10%; a codebase with serious structural debt may need 30% for a few quarters. The key is a protected, non-zero share every sprint, not a heroic one-off effort.

Should we stop building features to pay down technical debt?

Almost never. Stopping features destroys trust and usually does not fix the underlying habits that created the debt. The exception is genuinely dangerous debt — security, data integrity, or compliance failures — which should be treated as incidents, not scheduled work.

How do we convince non-technical stakeholders to fund debt repayment?

Translate every item into time, risk, or blocked revenue: hours lost per month, incidents caused, features it delays. Then report progress the same way. Stakeholders fund lead time and reliability; they do not fund code beauty, and a good plan does not ask them to.

Is a full rewrite better than paying down debt gradually?

Rarely. Rewrites discard years of embedded business knowledge, take longer than estimated, and deliver nothing until the end. If a large replacement is genuinely needed, build it alongside the old system and migrate piece by piece, retiring old code only after the new code has proved itself in production.

How long before a repayment plan shows results?

Small, high-interest items often pay back within weeks — a daily annoyance removed, a report that stops needing manual fixes. Structural improvements take quarters. Judge the plan on a rolling basis: are estimates for similar changes getting smaller, and are repeat incidents falling? If both move in the right direction, the plan is working.

A plan you can start this week

You do not need a consultancy engagement to begin. This week, run the register session, cap it at fifty items, and agree the capacity percentage with whoever owns the roadmap. Next sprint, schedule one high-interest fix and one quick win, and protect the capacity when a feature slips — that is exactly when the rule is tested. Review monthly, retire what no longer matters, and report progress as time saved and risk removed. Debt will never reach zero, and it does not need to: a visible register, protected capacity, and an honest sequence are enough to keep building on. If your team needs help with the register or the first hard sequencing calls, our custom coding and API development team does this work with clients every week — reach us via our contact page.