Short on time? Technical debt is the extra effort that messy or outdated code adds to every change. Measure it by the time it costs, find the hot spots you change most, pay it down in small steps with tests, reserve a share of each sprint and explain the cost in business terms. Not all debt needs paying, so focus on code that slows you now.
Every software team has shortcuts in its past. A quick fix before a deadline, a library that was never updated, a design that fit last year’s needs. Over time these make new work slower and riskier.
That slowdown is technical debt. This article explains how to measure it and pay it down in plain terms. It suits a start-up with one product and a large company with many systems.
Key takeaways
- Technical debt is a cost that shows up as slower changes, more bugs and higher risk.
- Measure it by effort lost and by where change happens, since code size says little.
- Pay down debt in small steps in code you touch often.
- Reserve time every sprint, and protect it.
- Talk about debt in business terms: speed, risk and cost.
What technical debt means
Martin Fowler explains technical debt with a loan metaphor from Ward Cunningham. The messy parts of a system, which he calls cruft, work like a debt. The extra effort needed to add features is the interest. Cleaning up is like paying off the principal.
He gives a simple example: a confusing structure turns a four-day feature into six days, and the two extra days are the interest. He also notes that you pay interest only when you work in that code. Messy code that nobody touches costs little.
Debt can be deliberate or accidental. A team may choose a shortcut to meet a date and plan to fix it later. Or the team may find, after learning more, that an old design was poor. Both are debt, and both can be managed.
Where debt comes from
- Deadlines and rushed releases.
- Changing needs, so old designs no longer fit.
- Outdated libraries, languages and platforms.
- Missing tests and documentation.
- Quick copies of code that spread.
- Team changes that lose knowledge. See software estimation and why estimates slip.
How to measure technical debt
No single number tells the whole story. Use several signals.
Time and flow
- Lead time: how long a change takes from idea to release.
- Rework: share of time spent fixing old problems.
- Change failure rate: how often releases cause incidents. See DORA delivery metrics.
- Estimates versus actuals in certain areas.
Code signals
- Code that changes often and has many bugs, called hot spots.
- Complex or very long modules.
- Low test coverage in important areas.
- Old dependencies with known flaws. See software supply chain security.
- Build and test times that keep growing.
People signals
- Surveys: ask developers where work hurts most.
- Onboarding time for new team members.
- Areas that only one person understands.
Business signals
- Outages and support costs from fragile systems.
- Features delayed by system limits.
- Cost of keeping old platforms running.
Combine the lists in a simple register: item, where it is, how often it is touched, what it costs and a rough fix effort.
Decide what to pay down
Not all debt deserves action. Fowler advises paying down gradually and focusing on code you change often. Stable, messy code that nobody touches can wait.
Rank items by:
- Interest paid: how much time and risk it costs each month.
- Chance to change soon: is a roadmap feature coming that touches it?
- Risk: security, data loss or outage potential.
- Fix effort: small wins first.
Ways to pay it down
- The boy scout rule: leave code a little better each time you touch it.
- Refactor with tests: add tests first, then restructure in small steps.
- Reserve capacity: many teams set aside a share of each sprint, often ten to twenty percent.
- Debt sprints for large items, used with care.
- Upgrade dependencies on a regular schedule.
- Automate: build, test and deploy checks. See our CI/CD starter pipeline and test automation strategy.
- Replace or modernise when a system is beyond repair. See legacy application modernization and web application architecture.
- Retire features nobody uses.
Prevent new debt
- Agree standards and review code. See code review practices.
- Keep a definition of done that includes tests and documentation.
- Record deliberate shortcuts with an owner and a date to revisit.
- Avoid borrowing quality to hit dates, since mess slows the very work that was urgent.
- Invest in developer tools and platforms. See platform engineering.
Talk to the business
Leaders respond to cost, risk and speed. Show examples:
- “This module adds two days to every change we make there.”
- “Three outages this year came from the same old service.”
- “Updating this library removes a known security risk.”
Link debt work to goals and to the technology investment business case. Report progress each quarter with the same measures. <!– expanded –>
What the industry research and engineering teams say
Three well-known sources give a firm base for the ideas in this article.
Google’s engineering practices set a clear standard for code review: approve a change once it clearly improves the overall health of the code, even if it is not perfect, and avoid letting good changes stall. Minor comments can be marked as optional “nits”. This standard keeps quality rising without freezing delivery, which is the balance technical debt work needs.
DORA, the long-running research programme on software delivery, lists capabilities linked to performance. Several relate directly to debt: code maintainability, continuous integration, test automation, deployment automation, version control, loosely coupled teams, documentation quality, database change management, working in small batches and monitoring and observability. Use the list as a checklist for where debt may hide.
Martin Fowler’s technical debt article adds a warning: borrowing against quality to ship faster often backfires, because the mess slows the very features that were urgent.
Types of technical debt
Debt is wider than messy code.
- Code debt: hard-to-read, duplicated or fragile code.
- Design debt: an architecture that no longer fits the product.
- Test debt: missing or unreliable tests.
- Build and release debt: slow, manual or flaky pipelines.
- Dependency debt: old libraries, frameworks and platforms.
- Infrastructure debt: servers and services that nobody dares to touch. See server refresh planning.
- Data debt: unclear definitions and poor quality. See data governance basics.
- Documentation and knowledge debt: know-how that lives in one person’s head.
- Security debt: known weaknesses left open. See vulnerability management.
Label each item in your register with a type. You will see patterns quickly.
A worked example: a checkout service
This example is illustrative.
A shop runs a checkout service built five years ago. Product wants to add three payment methods this year.
What the team sees:
- Each new payment method took about two weeks last time, and most of the time went on untangling old code.
- The service has few automated tests, so every change needs three days of manual checks.
- Two outages in a year came from the same fragile module.
- One developer understands the discount rules.
- The main framework version is near the end of its support.
What they do:
- Mark the payment module as a hot spot, since three features will touch it.
- Add automated tests around the current behaviour first.
- Refactor the module into a payment interface with one class per method, in small steps with each step released.
- Pair a second developer with the expert, and write down the discount rules.
- Schedule the framework upgrade for the next quarter, with its own tests.
- Track time per payment method before and after.
Result to look for: the third payment method should take far less time than the first. If it does, the story is easy to tell to leaders: the work paid back inside the same year. If not, find out why before doing more.
Working with product managers
Debt work competes with features. These habits help.
- Bring numbers. Show hours lost, incidents and delayed features.
- Tie it to the roadmap. Say which planned features the debt will slow.
- Offer options. Small now, bigger later, or do nothing, each with a cost.
- Agree a standing share of capacity so you do not argue every sprint.
- Show results. After the work, show the new lead time or incident count.
Small business and enterprise views
- Sole developer or small team: keep a short list, fix what you touch, update dependencies monthly and write a few tests around the riskiest code.
- Mid-size product company: run a quarterly review, reserve capacity and track lead time and change failure rate.
- Enterprise: assign owners per system, set standards for tests and upgrades, report debt as a risk to leadership and fund modernisation of the worst platforms. See legacy application modernization.
A simple quarterly report
Share one page with leaders.
- Top five debt items, with cost per month and plan.
- Delivery measures: lead time, deploy frequency and change failure rate.
- Reliability: incidents linked to known debt.
- Security: age of the oldest unpatched issue.
- Progress: items closed, items added and trend.
- Request: any extra budget or decisions needed.
When to rewrite, and when not to
Rewrites feel attractive and carry high risk. Prefer gradual replacement: build the new part beside the old one, move traffic in steps and retire the old part when it is empty. Consider a rewrite when the platform is unsupported, the business has changed so much that the design cannot fit it and the team can fund and finish the work. See composable enterprise for ways to replace parts safely.
Common mistakes
- Trying to fix everything.
- Measuring only lines of code or tool scores.
- Big rewrites with no clear gain.
- Hiding debt from leaders.
- No time reserved, so debt only grows.
- Cleaning up without tests.
A starting plan
- Build a technical debt register of twenty items.
- Mark the hot spots from change and bug data.
- Choose three items with the highest interest.
- Reserve a fixed share of each sprint.
- Review how to measure technical debt progress every quarter.
How SoftSapien supports technical debt reduction
SoftSapien’s engineers assess codebases, measure technical debt, plan safe refactoring and modernisation, add tests and automation and coach teams. See our custom software development and legacy application modernization services.
To take control of your codebase, use the contact page to chat with our team, send a message or schedule a free consultation call.
Frequently asked questions
What is technical debt?
The extra effort that messy, outdated or fragile code adds to every change. Martin Fowler compares the extra effort to interest on a loan.
How do we measure it?
Combine delivery signals such as lead time and change failure rate, code hot spots, developer surveys and business signals such as incidents and delayed features.
Should we pay all of it down?
No. Focus on code you change often or that causes risk. Stable, messy code that nobody touches costs little.
How much time should we reserve?
Many teams reserve ten to twenty percent of capacity, then adjust using the results.
Can SoftSapien help reduce our debt?
Yes, with assessment and safe refactoring. Contact SoftSapien through the contact page to chat with our team, send a message or schedule a free consultation call.