Ward Cunningham coined the term "technical debt" in 1992 as a metaphor to help business stakeholders understand why software teams sometimes need to revisit and rework existing code. The metaphor compares shortcuts in code to financial debt: you get short-term velocity now, but you pay interest on every future change until you pay down the principal.
Thirty-four years later, the metaphor has become so widely used that it has lost precision. Everything from poorly named variables to fundamental architecture flaws gets labelled "technical debt." This imprecision makes it harder to prioritise, harder to communicate, and harder to manage. If everything is debt, nothing is.
This article provides a structured approach to categorising, measuring, and reducing technical debt, based on practices we have refined across dozens of client engagements at Pepla.
Types of Technical Debt
Not all technical debt is created equal. Martin Fowler's technical debt quadrant classifies debt along two axes: deliberate vs inadvertent, and reckless vs prudent. This classification is essential for deciding how to respond.
Classify debt by intent and impact -- not all shortcuts are equal, and the response should differ accordingly.
Deliberate Prudent Debt
This is the "good" debt. The team knows they are taking a shortcut, understands the implications, and has a plan to address it. Example: "We will hard-code the exchange rate for the MVP launch and build the real-time currency service in Sprint 4." This is a rational business decision. The key is that it is documented, tracked, and scheduled for remediation.
Deliberate Reckless Debt
The team knows they are writing bad code and does it anyway, without a plan to fix it. "We do not have time for tests" or "We will clean this up later" (with no "later" on the backlog). This is the most damaging type because it accumulates fastest and is hardest to justify in hindsight.
Inadvertent Prudent Debt
The team did the best they could with their knowledge at the time, but later realised a better approach exists. "Now that we understand the domain better, we should have modelled it differently." This is unavoidable in any project where requirements are discovered iteratively, which is most projects.
Inadvertent Reckless Debt
The team does not know enough to recognise that they are creating problems. Junior developers without mentorship, teams without code review processes, or AI-generated code accepted without scrutiny. This debt is invisible until it causes failures.
The type of debt determines the response. Deliberate prudent debt needs tracking and scheduling. Deliberate reckless debt needs cultural and process change. Inadvertent debt needs education and better feedback loops.
Measuring Technical Debt
You cannot manage what you cannot measure. But measuring technical debt is notoriously difficult because much of it is subjective. Here are the approaches that provide actionable signal.
Code-Level Metrics
- Cyclomatic complexity: Measures the number of independent paths through a function. Functions with complexity above 10-15 are candidates for refactoring. Tools like SonarQube, ESLint, and ReSharper calculate this automatically.
- Code duplication: Percentage of the codebase that exists in duplicated form. Duplication above 5% typically indicates missing abstractions.
- Test coverage: Not a measure of quality, but a useful proxy for risk. Code with zero test coverage is high-risk code. Coverage below 40% for business-critical paths is a red flag.
- Dependency freshness: How far behind are your dependencies? Outdated dependencies accumulate security vulnerabilities and compatibility issues. Tools like Dependabot and Renovate track this automatically.
Delivery Metrics
The DORA metrics (Deployment Frequency, Lead Time for Changes, Change Failure Rate, Mean Time to Recovery) are indirect but powerful indicators of technical debt. When debt accumulates, lead time increases, change failure rate rises, and deployment frequency drops. These metrics make the impact of debt visible to non-technical stakeholders.
Developer Experience Metrics
- Build time: How long does it take to compile and run tests? Build times above 10 minutes kill developer productivity and encourage skipping tests.
- Onboarding time: How long does it take a new developer to make their first meaningful contribution? If it takes weeks, the codebase is carrying significant cognitive debt.
- Bug clustering: Which modules generate the most bug reports? Persistent hotspots usually indicate underlying structural problems.
The Tech Debt Register
The most practical measurement tool is a tech debt register: a living document (we use a dedicated section in the project backlog) that catalogues every known debt item with its category, estimated impact, estimated remediation effort, and priority. At Pepla, we review the tech debt register in every sprint planning session, right alongside feature work.
Measure technical debt in developer hours lost, not abstract quality scores.
Refactoring Strategies
Once you have identified and prioritised your debt, you need strategies for paying it down without stopping feature delivery.
The Boy Scout Rule
Leave the code better than you found it. Every time you touch a file, make one small improvement: rename a confusing variable, extract a function, add a missing test. These micro-refactorings compound over time. They are low-risk, require no dedicated sprint capacity, and gradually improve the codebase.
Strangler Fig Pattern
For large-scale debt (legacy systems, outdated frameworks, fundamental architecture issues), the strangler fig approach works well. Build new functionality using the new approach alongside the old system. Gradually redirect traffic from old to new. Eventually, the old system can be decommissioned. This avoids the risk and disruption of a big-bang rewrite.
Dedicated Refactoring Sprints
Some debt requires focused attention. Allocating one sprint out of every four or five for dedicated tech debt reduction is a common pattern. The advantage is that the team can tackle larger refactoring efforts that do not fit into feature sprints. The disadvantage is that stakeholders see a sprint with "no features delivered."
Embedding Debt Reduction in Feature Work
The most effective approach combines all three strategies. Every feature story includes a debt reduction component. If you are adding a new payment method, you also refactor the payment module's error handling. This keeps debt reduction continuous and ties it directly to business-visible work.
Communicating Debt to Stakeholders
The financial metaphor is powerful but overused. Stakeholders have heard "technical debt" so often that it has lost impact. Here are communication strategies that work better:
Translate to Business Impact
Do not say "we have technical debt in the payment module." Say "the payment module currently takes 3 weeks to add a new payment provider. After refactoring, it will take 3 days. The next three payment integrations on our roadmap will save 7.5 weeks of development time." Business leaders understand time-to-market and cost. They do not understand cyclomatic complexity.
Show the Trend
A single measurement is a data point. A trend line is a story. Show how lead time has increased over the past six months, or how bug rates in a specific module have grown quarter over quarter. Trends communicate urgency in a way that snapshots cannot.
Quantify the Risk
Some debt carries genuine business risk. An outdated framework with known security vulnerabilities is not just slow; it is a liability. Regulatory non-compliance due to inadequate logging is not just inconvenient; it carries financial penalties. Frame debt in terms of risk when risk is the real concern.
The most effective way to communicate technical debt is to stop using the phrase "technical debt" and instead talk about delivery speed, defect rates, and business risk. Speak the language your audience understands.
AI has made refactoring cheap enough that teams actually pay down debt instead of deferring it.
Budgeting for Debt Reduction
There are several models for allocating capacity to debt reduction, and the right one depends on your organisation:
- The 20% rule: Dedicate 20% of every sprint to non-feature work (debt reduction, tooling improvements, learning). This is simple, predictable, and sustainable. Google famously used a similar model with their 20% time.
- The tax model: Add a "debt tax" to every feature estimate. A feature that would take 5 days in clean code takes 7 days in a debt-laden codebase. Make the extra 2 days visible and allocate some of that time to cleaning up.
- The threshold model: Set quality thresholds (test coverage, build time, dependency age) and allocate debt reduction capacity when any threshold is breached. This is reactive but ensures that debt never exceeds a defined level.
- The investment model: Treat major debt reduction as a capital investment. Build a business case with expected returns (faster delivery, fewer bugs, lower risk) and secure dedicated budget. This works well for large-scale remediation.
At Pepla, we typically recommend starting with the 20% rule and adding the threshold model as the team matures. The combination provides both continuous improvement and guardrails against regression.
The goal is not zero debt -- it is a sustainable level that does not impede your ability to deliver value.
Technical Debt in the Age of AI
AI-generated code introduces a new dynamic to technical debt. Code produced by AI assistants is often syntactically correct and functionally adequate but architecturally naive. It does not understand your codebase's conventions, abstractions, or patterns. Left unchecked, AI-generated code creates a specific form of debt: functional code that does not integrate cleanly with the rest of the system.
The mitigation is straightforward: treat AI output as a first draft that requires engineering review. Apply the same code review standards to AI-generated code that you would apply to a junior developer's pull request. The speed benefit of AI generation is real; just ensure that speed does not come at the cost of coherence.
Technical debt is not a problem to solve once. It is a force to manage continuously. Like financial debt, the goal is not zero debt; it is a sustainable level that does not impede your ability to deliver value. With the right classification, measurement, and communication, technical debt becomes a manageable engineering concern rather than a vague source of frustration.




