---
title: What is technical debt?
description: "Technical debt explained—intentional vs accidental, why it appears, how to control it, outcomes of paying vs ignoring it, and when not to fight it."
image: "https://wavepillars.com/og-image.jpg"
url: "https://wavepillars.com/learn/engineering/what-is-technical-debt/"
---

**Technical debt** is the extra cost you pay on every future change because you chose—or drifted into—a shortcut today. **Ward Cunningham** introduced the metaphor in 1992: like financial debt, you borrow speed now and pay **interest** later in slower delivery, more defects, and harder estimates. The debt is not the shortcut itself; it is the **ongoing tax** until you repay or retire the code.

```
Speed now → cost later on every change
```

Most teams have debt. The question is not whether it exists, but whether it is **conscious, visible, and managed**—or hidden until a rewrite becomes the only honest option.

WAVEPILLARS treats technical debt as a **product and engineering decision**, not a moral label for "bad developers." Product chooses features vs stability; engineering makes trade-offs explicit and measurable.

## Key Takeaways

- Technical debt is the ongoing tax on change—not the shortcut itself.
- Intentional, documented debt can be leverage; accidental debt hides until estimates collapse.
- Old code is not automatically debt if it remains cheap to change.
- Allocate paydown based on measured impact, not a fixed percentage ritual.
- Discuss debt in business terms: slower delivery, defects, and incidents.
- Skip paydown on code you will replace or modules with no planned changes.

## What technical debt is

Technical debt shows up in code, architecture, tests, documentation, and infrastructure—but the unifying idea is the same: **change costs more than it should** because of a past choice that was not fully paid for.

### Intentional debt

**Intentional debt** is a documented trade-off: you ship faster now and accept a known payback later.

Examples:

- **MVP scope** — hard-code a workflow to validate demand before building a configurable engine
- **Spike promoted to production** — prototype proves the idea; refactor scheduled after customer traction
- **Defer refactor** — integrate with a third-party API through a thin adapter now; replace with a cleaner domain model once requirements stabilize
- **Buy time for a deadline** — skip non-critical tests or monitoring for a one-time regulatory cutover, with a ticket to harden afterward

Intentional debt is **leverage** when the business value of shipping now exceeds the interest you expect to pay—and when someone records **what** was borrowed and **when** payback is due.

### Accidental and creeping debt

**Accidental debt** was never decided. It accumulates through neglect, turnover, shifting requirements, and "we will fix it later" that never gets scheduled.

Examples:

- Copy-paste modules that diverged silently
- Missing tests on code everyone is afraid to touch
- Architecture that made sense for ten users but not ten thousand
- Comments and ADRs never written; only the original author knew why

Creeping debt is harder to manage because there is no owner and no payoff date—only a growing sense that **everything takes longer than it should**.

### Interest payments

Whether intentional or accidental, debt collects **interest** on every change:

- **Slower features** — simple stories touch fragile areas and balloon in scope
- **Higher defect rate** — regressions in untested or tangled code
- **Fragile estimates** — "two days" becomes two weeks when the team hits the mess
- **Onboarding friction** — new engineers need tribal knowledge to change anything safely
- **Incident frequency** — production surprises in the same subsystem, sprint after sprint

Debt categories overlap in practice. A missing test suite (test debt) makes a tangled module (code debt) expensive to refactor (architecture debt). Control the **impact on delivery**, not the label on the ticket.

## What technical debt is not

Confusing debt with other problems leads to guilt, pointless rewrites, and arguments that never reach product decisions. **Debt is about future change cost**, not aesthetics or backlog guilt.

| Often confused with debt | Why it is different |
|--------------------------|---------------------|
| **A single bug** | A defect in current behavior—not a structural trade-off that taxes every future change |
| **Missing features / backlog items** | Unbuilt value; the product never promised this capability yet |
| **All legacy code** | Old code is not automatically debt if it is stable, understood, and cheap to change |
| **Code style you dislike** | Preference, unless it measurably slows delivery or causes defects |
| **Normal learning curve** | You did not know the domain yet; debt is when you **know** a better design and defer it |
| **"We skipped tests once"** | One decision; debt is the **ongoing** cost until tests exist or the code is removed |
| **Technology you would not pick today** | A stack mismatch is not debt unless it blocks delivery or safety |

**Legacy** can be an asset: battle-tested, boring, and well-understood. **Debt** is when changing that code—or the system around it—costs more because of shortcuts left unpaid.

## Why technical debt appears

Debt appears for rational reasons. Treating it as a character flaw prevents honest conversation with product and leadership.

### Time pressure

Fixed dates—regulatory deadlines, conference launches, competitive windows—push teams to cut scope on **quality work** (tests, refactors, observability) while keeping feature scope. That is often the right business bet **if** payback is scheduled afterward.

### Uncertainty

When nobody knows what will sell or how users will behave, building the "correct" architecture upfront is guessing. Iterative delivery **expects** some debt early: you learn, then you harden. The failure mode is learning once and never revisiting the prototype paths—see [Agile, Scrum, and Kanban](/learn/leadership/agile-scrum-kanban-when-to-use/) for how iterative teams should inspect and adapt, not only ship.

### Prioritization

Product routinely chooses **features over hardening**. That is valid when stakeholders understand the interest rate. It becomes a crisis when engineering never surfaces the cost—stakeholders assume velocity is permanent.

### Knowledge gaps

Teams discover a better domain model, API shape, or boundary **after** shipping. The first version was not "wrong"; it was **early**. Debt appears when the improved model is understood but not integrated.

### Organizational friction

No capacity for refactors, platform work, or ops improvements. Every sprint is feature-only. Debt grows invisibly until incidents or attrition force the conversation.

### Scope creep on shortcuts

A spike or proof-of-concept ships to production "temporarily." Temporary becomes permanent because no one owns replacement. This is one of the most common sources of **accidental** debt.

### Team churn

Authors leave; tacit knowledge goes with them. Tests, docs, and ADRs were "not worth it" under deadline. New engineers change code carefully—or not at all—and velocity drops without a named cause.

## Why control technical debt

Debt is not automatically evil. Startups and new products **should** borrow when learning speed matters. Control means **inventory, measurement, and prioritized paydown**—not a zero-debt dogma that blocks shipping.

### Without visibility, product cannot trade off

Product owners need to choose **features vs stability** with real numbers, not engineering frustration vented in retrospectives. A visible debt register turns "the codebase is a mess" into "this epic costs us roughly two extra days per story until we pay it down."

### Uncontrolled debt destroys predictability

When shortcuts are forgotten, estimates lie. Sprints slip. Leadership loses trust. Engineers stop giving honest forecasts and pad everything—another hidden tax.

### Control is a loop, not a one-time cleanup

```
Borrow consciously → Track in backlog → Measure interest → Product prioritizes paydown → repeat
```

**Control mechanisms that work in practice:**

| Mechanism | What it does |
|-----------|----------------|
| **Debt register** | Backlog items (or linked tech tasks) with **impact**: affected area, cost of delay, suggested paydown |
| **Definition of Done** | Prevents **new** debt on every story—tests, review, docs per team agreement; see [DoD in the Agile article](/learn/leadership/agile-scrum-kanban-when-to-use/) |
| **Flow metrics** | Lead time, change failure rate, incident time in the same subsystem—interest you can show on a chart |
| **Time-boxed paydown** | 10–20% capacity per sprint, or regular hardening stories with product owner consent |
| **Architectural decision records (ADRs)** | Document intentional debt: what was borrowed, why, exit criteria, review date |

Debt control pairs well with [spec-driven development](/learn/ai/what-is-spec-driven-development/) when acceptance criteria and quality gates live in versioned artifacts the whole team can inspect—not only in engineers' heads.

## If you control debt vs if you do not

| Controlled | Uncontrolled |
|------------|--------------|
| Shortcuts are explicit and time-bound | Shortcuts forgotten; team says "it's always slow here" |
| Product chooses when to pay | Engineering surprises stakeholders with a "big rewrite" |
| Estimates stay roughly honest | Estimates become political fiction |
| Incidents trigger targeted fixes | Same classes of outages repeat |
| Sustainable pace | Burnout, attrition, rewrite proposals |

### Contoso: MVP with a payback plan

Contoso ships an MVP with a monolith and manual onboarding to hit a design-partner deadline. Engineering logs three debt items: replace hard-coded tenant rules, add integration tests on billing, split the reporting module. After two paying customers validate the model, the product owner schedules one debt item per sprint alongside features. Velocity dips briefly, then rises—new engineers ship without pairing on every change.

### Contoso: prototype that never graduated

Contoso ships the same kind of MVP but never schedules payback. Success brings more customers on the same prototype core. Each feature touches the same three files; estimates double. Incidents cluster in billing. Senior engineers leave. Leadership hears "we need a rewrite" with no incremental path—trust is already gone.

The difference is not initial shortcuts. It is **whether debt stayed visible and negotiable** after the first release.

## When not to control (pay down) technical debt

"Don't control" means **don't spend paydown budget now**—not "pretend it doesn't exist." Even when you defer fixing, record the debt and the trigger for revisiting it.

### Throwaway spikes

Code that will be deleted within days or after a demo does not need a refactor. Delete it when the question is answered.

### Pre–product-market fit

Before you know **what** to build, internal elegance loses to learning speed. Debt accumulated during discovery may die with a pivot. Invest in paydown when the product direction stabilizes and multiple releases will touch the same code.

### Imminent replacement

A subsystem is scheduled for replacement next quarter. Fixing internals that will be deleted is waste—unless the fix **reduces incident risk** during the transition. Be explicit about the cutoff date.

### Low lifetime value

A branch used by one client once, or a migration script run a single weekend, may never repay refactoring cost. Sunsetting beats polishing.

### Regulatory or event deadline

Ship, then harden—but **record** the debt, the risk accepted, and the payback window. "Ship then forget" is how accidental debt becomes a production legacy.

### Exploratory AI and vibe coding

Fast iteration with assistants before intent stabilizes is rational; see [What is vibe coding?](/learn/ai/what-is-vibe-coding/). Switch to [spec-driven development](/learn/ai/what-is-spec-driven-development/) and stricter [BDD acceptance criteria](/learn/leadership/what-is-behavior-driven-development/) when multiple people, agents, or releases depend on the same behavior staying stable.

### Stable code nobody touches

If a module is ugly but **rarely changed** and changes are low risk, paydown may rank below features with clear revenue impact. Revisit when change frequency or incident rate rises—that is interest showing up on the metrics.

## Anti-patterns

- **Debt as insult in code review** — "This is tech debt" without impact or payback proposal shuts down conversation
- **Cleanup sprint with no product owner** — Engineers refactor in a vacuum; product learns nothing and may reprioritize everything next sprint
- **Rewrite instead of incremental paydown** — Big-bang replacements often repeat the same missing controls
- **Lint score as sole metric** — Sonar or coverage numbers without business impact do not help product prioritize
- **Zero-debt policy** — Blocking all shortcuts kills learning and pushes trade-offs underground
- **Debt register as graveyard** — Items filed once and never groomed with product erode trust faster than no register at all

## Practices that work

1. **Name debt when you borrow** — Ticket, ADR, or backlog link at merge time; not six months later from memory.
2. **Describe impact in delivery terms** — "Adds ~1 day per billing story" beats "bad architecture."
3. **Groom debt with product** — Same refinement cadence as features; product owner orders paydown against value.
4. **Protect paydown capacity** — Fixed percentage or explicit hardening stories; do not rely on "extra time at the end."
5. **Measure interest** — Lead time and incidents in affected areas; show trends when asking for sprint capacity.
6. **Prevent new debt on new work** — Team [Definition of Done](/learn/leadership/agile-scrum-kanban-when-to-use/) enforced in review; do not add fresh shortcuts to already indebted areas without recording them.
7. **Prefer incremental paydown** — Strangle, extract, test-seam, and ship; avoid rewrite proposals without a phased plan product can follow.

## Summary

**Technical debt** is the ongoing cost of past shortcuts—intentional or accidental—paid as slower delivery, defects, and unreliable estimates. It is not every bug, every old line of code, or every missing feature. It **is** the extra work every change costs until you repay or remove the affected code.

**Control** means making debt visible, measuring its interest, and letting product prioritize paydown alongside features—not chasing zero debt or hiding trade-offs until a rewrite is the only story left. **Sometimes you should not pay down now**: throwaway spikes, pre-PMF learning, imminent replacement, and low-lifetime code can rationally defer refactoring—provided you still record what was borrowed and when you will revisit it.

Managed debt is a tool. Unmanaged debt is a tax nobody agreed to pay.

## FAQ

### What is technical debt and how much should we pay down per sprint?

Technical debt is the ongoing extra cost of change because of a past shortcut—intentional or accidental. There is no universal percentage; healthy teams allocate capacity based on measured impact: defect rate, cycle time inflation, and incident frequency in affected areas. A common pattern is ten to twenty percent of sprint capacity for paydown when interest is visible, with explicit tickets tied to outcomes—not aesthetic refactors.

### What is the difference between intentional and accidental debt?

Intentional debt is a documented trade-off: ship the MVP now, schedule payback after validation. Accidental debt accumulates through neglect, turnover, and deferred fixes nobody owns. Intentional debt can be leverage; accidental debt erodes estimates silently until everything touches fragile code.

### Is all legacy code technical debt?

No. Legacy code that is stable, understood, and cheap to change is an asset—battle-tested and boring. Debt is when changing that code costs more than it should because shortcuts were never repaid. Confusing age with debt leads to wasteful rewrites.

### How should product and engineering discuss debt with leadership?

Frame debt as product and delivery economics, not moral failure. Show interest payments: slower features, higher defect rate, fragile estimates, onboarding friction. Propose paydown tied to business outcomes—this refactor unlocks the next pricing tier; these tests reduce incident frequency—rather than abstract code quality.

### When should we not fight technical debt?

Do not refactor code scheduled for replacement, spikes meant to be discarded, or stable modules with no change on the roadmap. Pay down debt where you keep paying interest—every feature touches the same subsystem and estimates keep breaking.

## Internal Links

- [What should a software engineer know? Skills checklist & roadmap](/learn/engineering/software-engineer-knowledge-framework/)
- [How to Build a Telegram Bot with C#](/learn/engineering/how-to-build-telegram-bot/)
- [Telegram Webhook Integration in .NET](/learn/engineering/telegram-webhook-integration-dotnet/)
- [Agile, Scrum, and Kanban — when to use what](/learn/leadership/agile-scrum-kanban-when-to-use/)
- [Development metrics — what to measure and why](/learn/leadership/development-metrics-and-dora/)
- [What is spec-driven development (SDD)?](/learn/ai/what-is-spec-driven-development/)

```json
{"@context":"https://schema.org","@graph":[{"@type":"BlogPosting","headline":"What is technical debt?","description":"Technical debt explained—intentional vs accidental, why it appears, how to control it, outcomes of paying vs ignoring it, and when not to fight it.","datePublished":"2026-05-22","dateModified":"2026-07-11","url":"https://wavepillars.com/learn/engineering/what-is-technical-debt/","author":{"@type":"Person","name":"Kiryl Bahdanovich"},"publisher":{"@type":"Organization","name":"WAVEPILLARS","url":"https://wavepillars.com/"},"image":"https://wavepillars.com/og-image.jpg","timeRequired":"PT14M"},{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"What is technical debt and how much should we pay down per sprint?","acceptedAnswer":{"@type":"Answer","text":"Technical debt is the ongoing extra cost of change because of a past shortcut—intentional or accidental. There is no universal percentage; healthy teams allocate capacity based on measured impact: defect rate, cycle time inflation, and incident frequency in affected areas. A common pattern is ten to twenty percent of sprint capacity for paydown when interest is visible, with explicit tickets tied to outcomes—not aesthetic refactors."}},{"@type":"Question","name":"What is the difference between intentional and accidental debt?","acceptedAnswer":{"@type":"Answer","text":"Intentional debt is a documented trade-off: ship the MVP now, schedule payback after validation. Accidental debt accumulates through neglect, turnover, and deferred fixes nobody owns. Intentional debt can be leverage; accidental debt erodes estimates silently until everything touches fragile code."}},{"@type":"Question","name":"Is all legacy code technical debt?","acceptedAnswer":{"@type":"Answer","text":"No. Legacy code that is stable, understood, and cheap to change is an asset—battle-tested and boring. Debt is when changing that code costs more than it should because shortcuts were never repaid. Confusing age with debt leads to wasteful rewrites."}},{"@type":"Question","name":"How should product and engineering discuss debt with leadership?","acceptedAnswer":{"@type":"Answer","text":"Frame debt as product and delivery economics, not moral failure. Show interest payments: slower features, higher defect rate, fragile estimates, onboarding friction. Propose paydown tied to business outcomes—this refactor unlocks the next pricing tier; these tests reduce incident frequency—rather than abstract code quality."}},{"@type":"Question","name":"When should we not fight technical debt?","acceptedAnswer":{"@type":"Answer","text":"Do not refactor code scheduled for replacement, spikes meant to be discarded, or stable modules with no change on the roadmap. Pay down debt where you keep paying interest—every feature touches the same subsystem and estimates keep breaking."}}]}]}
```