12 Real-World Technical Debt Examples (And How to Pay Them Down)
Technical debt isn't a ghost in your legacy system — it's the PR you approved yesterday. 12 types from architectural drift to AI-generated bloat, with real incidents (Knight Capital's $440M loss, the Southwest meltdown) and a Debt Portfolio scoring framework to prioritize what to fix first.
We usually talk about technical debt like it's a ghost haunting a legacy system. The reality is much more mundane. It's the PR you approved yesterday because the product manager was breathing down your neck. It's the AI-generated boilerplate your junior developer merged without understanding. If you want to fix your engineering culture, you need to stop treating debt as a vague complaint and start categorizing it. Here are 12 concrete technical debt examples, a look at how AI is accelerating the problem, and a framework to manage your team's debt portfolio before bankruptcy hits.
Every team carries debt. The ones that ship well carry it intentionally.
What is Technical Debt? (The $2 Trillion Problem)
Technical debt is the implied cost of future rework caused by choosing an easy, limited solution now instead of a better approach that would take longer. Common examples of technical debt include skipping unit tests, hardcoding variables, ignoring software updates, and relying on manual deployment processes.
Ward Cunningham coined the metaphor in 1992 to explain to business stakeholders why software slows down over time. The analogy is financial: take a shortcut today, pay interest on it tomorrow. Skip enough payments, and the interest starts consuming your engineering budget.
How expensive is that interest? The Consortium for Information and Software Quality (CISQ) estimated in 2022 that the cost of poor software quality in the US alone reached $2.41 trillion. That figure includes operational failures, failed projects, and the accumulated drag of technical debt across industries. It is not a rounding error. It is the GDP of a mid-sized country.
The metaphor holds up because debt is not inherently bad. A mortgage lets you live in a house before you have saved the full price. A payday loan at 400% APR wrecks your finances. Technical debt works the same way. What matters is whether you took it on deliberately, whether you understand the interest rate, and whether you have a plan to pay it back.
The Technical Debt Quadrant (Fowler's Framework)
Martin Fowler refined Cunningham's metaphor into a two-axis framework that still does the best job of describing debt decisions:
| Deliberate | Inadvertent | |
|---|---|---|
| Reckless | "We don't have time for tests." | "What's a dependency injection?" |
| Prudent | "Ship now, refactor next sprint." | "We didn't know the requirements would change." |
Reckless + Deliberate is the team that knows better and cuts corners anyway. Reckless + Inadvertent is the team that lacks the experience to recognize the debt it is creating. Prudent + Deliberate is a healthy tradeoff: eyes open, repayment planned. Prudent + Inadvertent is the debt you only recognize later, once you know more about the domain.
Most organizations drift into the reckless-inadvertent quadrant without realizing it. AI code generation is pushing more teams there faster, because the code looks prudent even when the underlying decisions are not.
12 Types and Examples of Technical Debt
The most common types of technical debt include architectural debt, code design debt, infrastructure debt, testing debt, and knowledge debt. Recently, AI-generated debt has emerged as a new category caused by unverified code generation.
Think of your codebase as a Debt Portfolio. Some items are low-interest mortgages you can carry for years. Others are payday loans charging interest daily. You cannot manage the portfolio if you do not know what is in it.
Most catalogs of technical debt sort into four buckets. AI added a fifth.
| Category | What it looks like in practice | Examples below |
|---|---|---|
| Code & Design Debt | Hardcoded values, copy-pasted code, god classes, dead code left in the tree | #5, #11, #12 |
| Architecture & Infrastructure Debt | Monolithic systems, manual deployments, outdated servers, schema sprawl | #1, #2, #8, #9 |
| Process & Testing Debt | Skipped unit tests, flaky suites, missing documentation, knowledge in one head | #6, #7, #10 |
| Security & Upgrade Debt | Exposed credentials, unpatched CVEs, postponed framework migrations | #4 |
| AI-Generated Debt (the new category) | Plausible AI code that passes tests but nobody on the team fully understands | #3 |
The first four are the ones every engineer has met. The fifth is the reason this list needed rewriting: AI accelerates the other four faster than review can keep up.
1. Architectural Debt (The Monolithic Monster)
The Definition: Architectural debt accumulates when the high-level structure of a system no longer matches its operational demands. It is the gap between what the system was designed to handle and what the business now expects from it.
The Example: A fintech startup builds a monolithic Django application in 2019. It handles payments, user management, notifications, and reporting in a single deployable unit. By 2023, the team has grown from 4 engineers to 35. Every deployment requires coordination across six teams. A change to the notification template engine triggers a payment processing regression because both paths share an ORM layer that nobody fully understands anymore.
This is Complexity Drift: architecture that degrades not because of one reckless choice, but because of hundreds of reasonable micro-decisions made under pressure. Each PR looked defensible. The aggregate is a system where changing anything means understanding everything.
The Interest Rate: High and compounding. Deployment frequency drops. Lead time climbs. Onboarding gets harder. Teams start building workarounds instead of fixing the structure underneath, which adds another layer of debt. The strangler-fig pattern—gradually extracting bounded contexts into independent services—is a proven repayment strategy, but it takes sustained effort over quarters, not a spare afternoon.
2. Infrastructure Debt (The Southwest Airlines Scenario)
The Definition: Infrastructure debt lives below the application layer: provisioning, scheduling, network configuration, CI runners, deployment targets, and the operational plumbing people ignore until it fails.
The Example: In December 2022, Southwest Airlines melted down. While other carriers recovered from a winter storm within days, Southwest cancelled nearly 16,900 flights over ten days. The root cause was not the weather. It was a crew scheduling system so outdated that it could not reassign pilots and flight attendants once the cascade started. The airline's unions had warned about the system for years. Leadership deferred the upgrade anyway.
The system held under normal conditions. It collapsed under stress. That is classic infrastructure debt.
The Interest Rate: Infrastructure debt is deceptive because it appears cheap right up until it becomes existential. It is the payday loan in the portfolio. For a while, the interest rounds down to zero. Then a bad week arrives and the bill comes due in outages, customer trust, and public scrutiny.
3. AI-Generated Debt (The Infinite Intern)
The Definition: AI-generated debt is the hidden complexity introduced when teams accept code from AI assistants without enough review, understanding, or architectural context.
The Example: A mid-level developer uses Copilot to generate a data transformation pipeline. The code is syntactically clean, passes the existing tests, and ships in a day instead of a week. Three months later, a performance investigation shows the pipeline is making redundant database calls inside a loop. The AI produced something plausible, but it had no understanding of the team’s data volume or service boundaries. Fixing it means rewriting the pipeline and the two services that now depend on its output format.
This is the AI Debt Iceberg. Above the waterline: clean syntax, passing tests, fast delivery. Below the waterline: duplicated logic, missing context, poor assumptions about scale, and architectural choices that no human can defend because no human fully made them.
Think of AI as the Infinite Intern. It never gets tired, never pushes back, and never learns your system in the way a strong engineer does. It produces work faster than your team can review it. The debt does not come from the AI being obviously wrong. It comes from the AI being plausible enough to slip past the scrutiny a shaky human PR would attract.
I've written extensively about how to review AI-generated code with the rigor it demands. The short version is simple: AI drafts, humans own. Every line an AI writes needs a human who can explain why it exists and what tradeoff it represents. That habit starts early — treating AI as a mentor rather than a code vending machine keeps developers in the driver's seat instead of merging output they cannot defend.
The Interest Rate: Accelerating. The more AI-generated code you accept without deep review, the more your codebase fills with logic nobody truly understands. Debugging takes longer because nobody authored the code in a meaningful sense. The interest compounds with every AI-assisted PR that gets a quick approval because it looked tidy.
4. Security & Upgrade Debt (Dependency Hell)
The Definition: Security and upgrade debt accumulates when teams keep postponing dependency updates, framework migrations, or security patches because the current system appears stable.
The Example: A B2B SaaS platform runs on .NET 6. The team knows .NET 8 is available and the .NET 6 support window is closing. But the migration means updating 47 NuGet packages, retesting integrations with three payment providers, and handling breaking changes in the authentication middleware. Each quarter, the work gets pushed to the next one. Then a CVE lands for a transitive dependency three levels deep in the package graph. The patch only supports .NET 8. The migration that could have been planned now has to happen under incident pressure.
The Interest Rate: Low and steady until a vulnerability disclosure turns it into a fire. Monthly upgrades are boring, and that is the point. Teams that keep dependencies moving in small increments buy cheap insurance. Teams that batch upgrades into annual projects pay for it later in risk, stress, and broken assumptions.
5. Code Design Debt (The God Class)
The Definition: Code design debt sits at the class, method, and module level. It shows up as poor abstractions, leaking responsibilities, and code that grew feature by feature without the refactoring needed to keep it sane.
The Example: An e-commerce platform has an OrderService class that started at 200 lines. Over two years and forty contributors, it grows to 4,300. It handles order creation, inventory checks, payment processing, email notifications, tax calculations, and audit logging. Every new feature touches OrderService. Every merge conflict seems to happen there. Junior developers avoid it. Senior developers work around it by duplicating logic elsewhere.
This is what happens when teams let simple features become monsters. Not through laziness. Through gravity. It is always easier to add one more method to the class that already contains most of the context.
The Interest Rate: Moderate but persistent. God classes rarely cause a dramatic outage by themselves. They cause drag: slower reviews, more merge conflicts, more accidental coupling, and more fear around changes. The bill arrives in frustration and lost momentum.
6. Cognitive Debt (Ghost Documentation)
The Definition: Cognitive debt is the cost imposed on developers who have to understand a system through archaeology instead of clear documentation. It includes outdated READMEs, misleading comments, stale runbooks, and tribal knowledge trapped in one person’s head.
The Example: A team’s API documentation says the /users endpoint accepts a role parameter with values admin, editor, and viewer. The codebase added superadmin and auditor eighteen months ago. A new developer builds an integration against the documented API, ships it, and discovers in production that the role-mapping logic is incomplete. The documentation did not lie when it was written. It lies now because nobody kept it alive.
These are Ghost Docs: documentation that haunts the codebase by sounding confident while being wrong. AI tools make this worse. They generate READMEs and inline explanations from code patterns, which means they can produce polished documentation that reflects the model’s guess, not the team’s intent. You end up with a second layer of misinformation generated at speed.
The deeper problem ties back to how teams decay when information stops flowing. Cognitive debt is not mainly a tooling issue. It is a team habit issue.
The Interest Rate: Slow but corrosive. Every hour spent reverse-engineering intent from code is an hour not spent building. Sprint dashboards rarely show it. Onboarding time, repeated mistakes, and integration bugs do.
7. Quality Debt (Test Gaps & Flaky Suites)
The Definition: Quality debt is the gap between what your test suite reports and the confidence it actually gives you. Coverage numbers can look healthy while the tests themselves are weak, brittle, or pointed at the wrong things.
The Example: A team reaches 87% code coverage. Leadership celebrates. But nearly a third of the test suite consists of AI-generated tests that assert implementation details instead of behavior. They verify that a mock was called rather than that the system produced the right outcome. When a pricing bug reaches production, the team discovers they had Coverage Without Confidence.
At the same time, twelve tests are marked [Skip] because they have been flaky for months. Nobody gets time to fix them. Nobody remembers what they were meant to catch. The suite is green, but nobody trusts it.
The push for speed—especially when AI is increasing code output—makes this worse. When throughput becomes the loudest metric, psychological safety around slowing down to write real tests erodes.
The Interest Rate: Quality debt is a Silent Tax on every release. Each deployment carries more risk than the team thinks. The cost shows up in hotfixes, regression hunts, and the gradual loss of trust in the test suite. Once that trust is gone, teams stop treating red and green as meaningful signals. That is when quality debt stops being a nuisance and starts distorting engineering behavior.
8. Deployment Debt (Manual Release Pipelines)
The Definition: Deployment debt accumulates when getting code from a developer’s machine to production depends on manual steps, undocumented rituals, or one person’s memory.
The Example: A healthcare software company deploys every two weeks. The release process involves a senior engineer following a 47-step checklist in a shared Google Doc, manually updating configuration across three environments, and SSH-ing into a production server to restart services. That engineer takes a two-week vacation. The release fails at step 31. Nobody else knows what “verify the cert rotation completed” means in practice.
The Interest Rate: Linear but relentless. Every manual step is a failure point. Every deployment that depends on a single person is a bottleneck. The debt does not need a catastrophe to hurt you. It drains throughput every release and conditions the team to fear shipping.
9. Data Debt (Schema Sprawl)
The Definition: Data debt lives in schemas, migrations, pipelines, and all the assumptions hidden in how the system stores information.
The Example: A marketing analytics platform adds a metadata JSON column to its campaigns table as a quick way to store flexible attributes. Over three years, fourteen features write different structures into that column. Some rows contain { "source": "email" }. Others use { "campaign_source": "email", "version": 2 }. A third variation nests the source inside tracking. Every query against the column now requires defensive parsing. A reporting feature that should have taken one sprint takes three because the team first has to figure out what is actually in production.
The Interest Rate: Data debt compounds faster than code debt because data outlives the code that wrote it. You can refactor a class this afternoon. Cleaning up years of inconsistent production data is a migration program with rollback plans, backfills, and business risk attached.
10. Knowledge Debt (The Bus Factor of One)
The Definition: Knowledge debt is the organizational risk created when critical system understanding is concentrated in too few people.
The Example: A payments team has one engineer who built the reconciliation system four years ago. She is the only person who understands the edge cases in the settlement logic, the only one with access to the payment processor’s admin panel, and the only one who knows why the nightly batch job runs at 2:47 AM instead of midnight. She gives notice on a Friday.
This is a bus factor of one, and it is more common than most teams want to admit. Knowledge debt is not mainly a code problem. It is a team-structure problem. It connects directly to how new team members struggle to land when critical context lives in one person's head instead of shared artifacts.
The Interest Rate: Zero until the person leaves. Then effectively infinite. There is no gentle slope here. There is a cliff.
11. Defect Debt (The Known-Bug Backlog)
The Definition: Defect debt is the accumulation of known bugs that have been triaged, acknowledged, and left in the backlog long enough to become normal.
The Example: A project management SaaS has 340 open bugs. Of those, 280 are labeled “low priority.” Inside that pile are a timezone calculation error affecting half-hour offset regions like India, Iran, and Nepal; a CSV export that silently drops rows containing Unicode characters; and a race condition in notifications that occasionally sends duplicates. None of these bugs is catastrophic on its own. Together, they make the product feel unreliable. Customer support spends 15 hours per week handling issues tied to “known bugs.”
The Interest Rate: Each bug looks cheap in isolation. The aggregate creates a reputation tax. Users do not file bug reports forever. Eventually they assume the product is flaky and leave.
12. Feature Debt (Dead Code & Abandoned Flags)
The Definition: Feature debt is the cost of code that was shipped but never cleaned up: abandoned feature flags, dead branches, obsolete toggles, and experiments that became permanent by inertia.
The Example: On August 1, 2012, Knight Capital Group deployed new trading software that accidentally activated dead code—an obsolete market-making function left in the codebase for years. In 45 minutes, the firm lost $440 million. The dead code executed trades nobody intended, at a speed no human could stop. Knight Capital survived only because a consortium of investors injected $400 million in emergency capital. The firm was acquired months later.
Most teams are not one stale feature flag away from destroying a trading firm. But the pattern is the same. Every flag that stays past its expiration date adds another branch. Every branch adds another thing to reason about. That added complexity means the next developer is more likely to misunderstand the path they are touching.
The Interest Rate: Near zero for a long time, then catastrophic. Dead code is an unexploded device in the basement. The danger is easy to ignore because most days nothing happens.
Managing Technical Debt: The Debt Portfolio Approach
Categorizing debt helps. Managing it takes a system.
Treat the codebase like a Debt Portfolio. Each debt item has three properties:
- Impact: How much does this debt slow the team down when it is encountered?
- Probability: How often does the team encounter it?
- AI Acceleration: Is AI tooling making this debt accumulate faster?
A God Class with an impact score of 8, encountered daily (probability 9), with moderate AI acceleration (AI keeps adding methods to it—score 6) has a portfolio risk score of 8 × 9 × 6 = 432. A dead feature flag with impact 3, encountered rarely (probability 2), and no AI acceleration (score 1) scores 6.
This is not accounting. It is triage. The point is to move the conversation from “we should fix stuff” to “here is the ranked list, and here is what we are paying down this quarter.”
The hard part is not identifying debt. It is resisting fantasy solutions.
You cannot stop feature work for a magical refactoring month and expect the problem to stay solved. Teams try this all the time. Leadership approves a “tech debt sprint.” The team spends two weeks cleaning up. Then the next six months are feature-only because everyone feels they already paid the debt tax. The backlog grows back faster than before.
The sustainable model is a tax, not a holiday. Allocate 15–20% of every sprint to debt repayment. Not as a side quest. Not as a reward for finishing feature work early. As a planned, protected line item in normal delivery.
This is a technical leadership problem, not an individual developer problem. The lead who protects that 15–20% is usually doing more for long-term delivery than the one who squeezes out one extra feature per sprint.
How to Reduce Technical Debt in 3 Steps
Audit and inventory existing debt.Categorize debt using the Technical Debt Quadrant.Allocate 15–20% of every sprint to refactoring.
The steps are straightforward. The discipline is the hard part.
Step 1: Inventory
Run a debt audit. This is not only a tooling exercise, though tools can help. Sit the team down and ask blunt questions.
What slows you down? What do you avoid touching? What do you route around instead of fixing? What breaks often enough that people have started treating it as normal?
Capture each item with a one-line description, the debt type from the categories above, and a rough severity rating. Do not over-design the process. A shared spreadsheet is fine. The goal is visibility.
If you want better answers, ask engineers to name the last three things that caused friction in real work rather than asking for abstract complaints. People remember yesterday’s pain more accurately than they describe systemic pain in a vacuum.
Step 2: Score and Categorize
Plot each item on Fowler’s quadrant. Was the debt taken on deliberately or inadvertently? Was the choice reckless or prudent? Then score it using Impact × Probability × AI Acceleration.
The quadrant tells you why the debt exists, which matters if you want to prevent more of it. The score tells you what to fix first, which matters if you want the backlog to move.
Debt in the reckless-inadvertent quadrant usually points to a skills gap, a review gap, or a process problem. If you fix the code but ignore the source, the same debt comes back in a new form. Debt in the prudent-deliberate quadrant is not a moral failure. It is a tradeoff that needs a repayment date.
Step 3: Allocate and Protect
Take the ranked list and assign the top items to the next sprint’s 15–20% allocation. Treat them like normal work: estimated, assigned, reviewed, shipped.
Then track whether the portfolio is improving. If the risk score trends down over time, the system is working. If it stays flat or rises, the team is either underfunding debt repayment or still generating debt faster than it can remove it. In practice, the usual causes are predictable: AI-generated code getting light review, tests getting skipped under deadline pressure, or recurring architecture decisions being made by convenience.
The metric that matters is not “debt items closed.” It is developer friction over time.
Are deployments getting faster or slower? Is onboarding time shrinking or growing? Are incident rates dropping? Are engineers less hesitant to change high-value parts of the system?
Those are the signals that tell you whether debt repayment is changing reality instead of producing tidy Jira tickets.
Frequently Asked Questions
Is technical debt always bad?
No. Prudent, deliberate debt is a legitimate engineering strategy. Shipping with a known shortcut to hit a market window can be rational if the team records the tradeoff and schedules the repayment. The danger is unmanaged debt that compounds quietly until it starts shaping every delivery decision.
How do you measure technical debt?
There is no single metric. Static analysis tools such as SonarQube and NDepend can quantify complexity, code smells, and other maintainability signals. That helps, but it is incomplete. The most useful measure is still friction: ask the team what slows them down, rank it, and track whether those pain points improve. The portfolio scoring model—Impact × Probability × AI Acceleration—gives you a rough ranking that is far more actionable than a vague sense that the codebase feels messy.
How does AI create technical debt?
AI code generators produce syntactically clean output that passes tests but lacks architectural context. The code looks senior-level, so it receives less scrutiny than a junior developer's PR would. Over time, this introduces duplicated logic, unnecessary abstractions, and dependencies on patterns the AI inferred from training data rather than your system's actual constraints. The result is a codebase where nobody fully understands why the code is structured the way it is — which is the definition of high-interest debt.
What are the four types of technical debt?
The four categories most teams use are code and design debt, architecture and infrastructure debt, process and testing debt, and security and upgrade debt. This article breaks those into 12 concrete examples and adds a fifth category for the AI era — AI-generated debt — because unverified machine output now accumulates faster than the original four combined.
What is the 80/20 rule for technical debt?
Roughly 80% of your slowdown comes from about 20% of your debt. A handful of high-traffic problem areas — the God Class everyone has to edit, the deployment step that breaks every release — generate most of the daily friction. That is the entire point of scoring debt by Impact × Probability × AI Acceleration: it surfaces the 20% worth paying down first, instead of spreading repair effort evenly across a backlog where most items barely cost you anything.
What is another name for technical debt?
Technical debt is also called tech debt, code debt, or design debt. Older terms describe the same decay from a different angle: code rot, software rot, and software entropy. Ward Cunningham coined "technical debt" in 1992 specifically as a financial metaphor, so non-engineers could understand why deferred cleanup keeps getting more expensive the longer you ignore it.
Don't Let the Robot Take Out a Loan in Your Name
Technical debt has always been part of software development. What changed is the rate of accumulation. AI tools can produce code faster than teams can properly review it. Product pressure compresses timelines. Teams start taking on debt inadvertently, at scale, while telling themselves they are moving faster.
The answer is not to ban AI or stop shipping. It is to know what you owe, decide what matters, and protect the time to pay it down. Every sprint. Under normal operating pressure, not only after an incident.
Your codebase is a financial instrument. Treat it like one.
If you do, technical debt becomes manageable. If you do not, it becomes your operating model.