Frank Ray

Software expert witness for IT and software development disputes.

  • Welcome
  • Expert Witness
  • Fees and Charges
  • Resources
  • Handbook
  • Writing
  • Blog
  • About
  • Contact

Managing Technical Debt

How shortcuts accumulate, what they actually cost a team, and how to make technical debt visible, budget its repayment, and prevent the worst of it through better requirements.

You need to add a simple feature to the payment system. Should take two days, maybe three.

But first you need to understand why the payment logic works the way it does. Navigate around that workaround someone added in 2019. Update three deprecated libraries that are throwing security warnings. Refactor two functions that were “temporary” four years ago.

Two weeks later, you’re still working on it. The “simple” feature exposed ten other problems. Nobody documented why things were built this way. Every change risks breaking something else.

Technical debt is the cost of shortcuts you took, or inherited, to ship faster. It’s when rushed code, missing tests, or “we’ll fix it later” decisions accumulate to the point of slowing down future development.

And you’re paying interest on it right now.

What Technical Debt Actually Is

Ward Cunningham coined the term in 1992, comparing software shortcuts to financial debt: borrow against the future to ship today, but you’ll pay interest until you refactor.

Technical debt shows up as:

  • Rushed code written to meet tight deadlines
  • Missing or outdated documentation
  • Skipped automated tests (“we’ll add them later”)
  • Hardcoded values instead of configuration
  • Deprecated dependencies nobody’s updated
  • “Temporary” workarounds that became permanent
  • Architecture that doesn’t scale anymore

Not all debt is bad. Sometimes you deliberately choose to ship fast and refactor later. That’s good debt—you made a conscious trade-off and planned to address it.

The problem is bad debt: shortcuts taken unconsciously, forgotten promises to refactor, technical decisions made without understanding the long-term cost. This is the debt that compounds silently until your development velocity collapses.

Think of it like the Slow Code Movement in reverse—sometimes rushing actually makes you slower.

Why Technical Debt Accumulates

Scenario 1: Deadline Pressure

A development team has three weeks to launch. They skip proper error handling, hardcode configuration values, and bypass the code review process. It ships on time.

Six months later, production crashes. Nobody understands the payment system logic. The error logs are useless. The original developers moved to other projects. Fixing it takes four weeks because the technical debt made the system incomprehensible.

Scenario 2: Poor Requirements

A developer receives a vague user story: “Users should be able to upload documents.” No size limits specified. No format restrictions. No security requirements. No performance targets.

The developer makes reasonable assumptions: support any file type, unlimited size, store everything locally. Those assumptions become permanent. Two years later, the database is full of 500MB PDFs and someone uploads malware through a disguised executable.

This is where gathering requirements properly prevents technical debt before it starts—clear requirements mean fewer costly assumptions.

Scenario 3: “Good Enough” Culture

The feature works in testing. Technically meets requirements. Ship it.

Nobody notices it takes 30 seconds to load with real data. Nobody tests it on mobile. Nobody considers what happens when user volume doubles. “Good enough” becomes permanent, and technical debt accumulates invisibly.

The Real Cost

You’re already paying for technical debt. The only question is whether you’re paying efficiently.

Direct Costs You’re Seeing

  • Simple changes take weeks instead of days
  • Senior developers spend their time maintaining old code instead of building features
  • New developers need three months to onboard (should be three weeks)
  • Bug rates climbing despite a “stable” codebase
  • Production incidents increasing
  • Team morale tanking as everyone fights the codebase

The Hidden Number

In my experience, teams waste well into six figures a year on rework that traces back to poor requirements—the clarification meetings, the misunderstood tickets, the features built twice.

Technical debt works the same way. You’re paying interest whether you acknowledge it or not.

Example: one client burned £180,000 over three months building new features on top of undocumented technical debt. A “simple” feature exposed architectural problems nobody had written down. The rework cost more than hiring a senior developer for 18 months to fix the debt first.

Every organisation pays for technical debt. Either explicitly, by scheduling time to address it. Or implicitly, through the costs of not having it: constant rework, blocked developers, features that take three times longer than they should.

How to Manage Technical Debt

1. Make It Visible

Technical debt is invisible until you document it. Nobody tracks it, nobody prioritises it, and it accumulates silently.

Make it trackable:

  • Create a debt backlog (not just mental notes)
  • Document “why we built it this way” when taking shortcuts
  • Tag code with TODO comments that explain the context
  • Discuss debt in sprint planning, not just features

If it’s not visible, it won’t get fixed.

2. Budget for Payback

Teams that don’t allocate time for debt reduction eventually grind to a halt.

Allocate deliberately:

  • Reserve 20% of each sprint for debt reduction
  • Follow the “Boy Scout rule”—leave code better than you found it
  • Schedule refactoring alongside feature work
  • Don’t accept “we’ll fix it later” without a ticket and a timeframe

As the Slow Code Movement reminds us: sometimes going slower makes you faster. Paying down debt now prevents expensive emergencies later.

3. Prevent Accumulation

The best way to manage debt is not creating it in the first place.

Prevention strategies:

  • Get better requirements up front—fewer assumptions mean less debt
  • Make code reviews non-negotiable
  • Specify non-functional requirements from the start (performance, security, maintainability)
  • Write automated tests as you build features
  • Challenge “temporary” solutions before they become permanent

4. Know What Matters

Not all technical debt deserves equal attention. Prioritise ruthlessly.

High-interest debt (fix immediately):

  • Security vulnerabilities
  • Performance bottlenecks affecting users
  • Code that blocks other development
  • Compliance violations

Low-interest debt (defer or accept):

  • Inconsistent naming conventions
  • Missing comments in stable code
  • Old but functional libraries
  • Aesthetic issues that don’t impact users

Focus on debt that’s costing you velocity or exposing you to risk. Everything else can wait.

5. Know When to Declare Bankruptcy

Sometimes the debt is so severe that paying it down incrementally doesn’t make sense. A complete rewrite might be cheaper.

Signs you need a rewrite:

  • Every change breaks multiple unrelated features
  • Onboarding takes longer than building new systems
  • The original architecture can’t support current requirements
  • Security or compliance issues are systemic, not fixable

But usually, you don’t need a rewrite. Most debt is manageable through disciplined reduction. Rewrites are expensive, risky, and often recreate the same problems in new ways. When a replacement genuinely is warranted, replacing a legacy system is its own discipline—the hardest part is recovering what the old system quietly did that nobody wrote down.

Common Mistakes

❌ Thinking you’ll “come back to it.” You won’t. If it’s not scheduled with allocated time, it won’t happen. Technical debt doesn’t age well—it compounds.

❌ Letting perfect be the enemy of good. Some debt is acceptable. Shipping working software with minor technical compromises is better than never shipping at all. Know the difference between “needs improvement” and “genuinely broken.”

❌ Not communicating debt to stakeholders. Non-technical stakeholders don’t see technical debt slowing you down. They just see “developers taking longer for simple features.” Explain it in business terms: “This will take three weeks instead of one because of shortcuts we took last year. We can address the root cause in two sprints if we prioritise it.”

❌ Treating all debt the same. Security debt is different from aesthetic debt. Prioritise based on actual impact, not just what annoys developers most.

Technical Debt Isn’t Failure—It’s Reality

Every codebase has technical debt. Every development team accumulates it. The question isn’t “do we have debt?” but “are we managing it deliberately?”

Teams that succeed with technical debt:

  • Make it visible instead of hiding it
  • Budget time to address it alongside features
  • Prevent new debt through better practices
  • Prioritise ruthlessly based on actual cost
  • Communicate it to stakeholders in business terms

Teams that fail with technical debt:

  • Pretend it doesn’t exist
  • Assume they’ll “get to it eventually”
  • Let perfect be the enemy of good
  • Don’t track or measure it
  • Let it compound silently until velocity collapses

Technical debt is especially pernicious in remote, offshore, and distributed teams. When developers are distant from users and stakeholders, unclear requirements lead to assumptions. Those assumptions become permanent. The debt multiplies.

Better requirements mean less technical debt. When developers understand what they’re building and why, they make better technical decisions. When the important details are surfaced early, developers don’t need to guess. Specify non-functional requirements from the start and performance and security get built in rather than bolted on.

The debt you accumulate today determines your development velocity tomorrow. Manage it deliberately, or it will manage you.

Left to compound, that same debt sometimes ends up as the subject of a dispute—the gap between the system a buyer paid for and the one they got. Reading it that way, after the fact, is a job for an expert witness rather than a development team, but it’s exactly the habits in this chapter that such an assessment looks for.

Better Software Requirements

A handbook for software development teams and their managers.

  1. 01 Introduction
  2. 02 Gathering Requirements
  3. 03 Writing Requirements
  4. 04 Reviewing Requirements
  5. 05 Implementing Requirements
  6. 06 Requirements for Agile Teams
  7. 07 Remote, Offshore and Outsourced Teams
  8. 08 Replacing Legacy Systems
  9. 09 Managing Technical Debt
  10. A Functional vs Non-Functional Requirements
  11. B Non-Functional Requirements: Examples & Templates

Facing a software or IT dispute?

A confidential, no-obligation discussion, at any stage from pre-action assessment to trial.

info@bettersoftware.uk 0786 8349 426 (UK)

Practice

  • Expert Witness
  • Fees and Charges
  • Resources
  • Contact

Background

  • About
  • Handbook
  • Writing
  • Blog

Software expert witness services. © 2026 Frank Ray