Technical Debt
Shortcuts in code act like financial debt: they let you ship faster now and charge interest on every future change.
Symptoms
- Simple changes take days because you have to work around old hacks to avoid breaking things.
- The same bug keeps returning in different forms. You fix it in one place; it reappears where duplicated logic drifts out of sync.
- New team members (and agents) produce inconsistent code because there’s no clear pattern to follow, only a patchwork of past shortcuts.
- Large parts of the codebase have no tests. Nobody adds them because the code wasn’t designed to be testable.
- You avoid touching certain files or modules. Everyone knows they’re fragile, so they route around them instead of fixing them.
- Onboarding takes longer every quarter. The gap between what the architecture diagram says and what the code actually does keeps widening.
Why It Happens
Ward Cunningham coined the metaphor in 1992. He compared shipping code you don’t fully understand to taking on financial debt: you get the money now (working software), but you pay interest later (the cost of working in code that doesn’t reflect your current understanding). The original metaphor was narrow and specific. It described the gap between what you’ve learned about a problem and what the code expresses. The term has since expanded to cover almost any kind of deferred work in a codebase.
Martin Fowler sharpened the taxonomy with his Technical Debt Quadrant. One axis is deliberate versus inadvertent: did you know you were taking on debt, or did you only realize it later? The other is reckless versus prudent: did you skip the work because you didn’t care, or because you made a conscious tradeoff? “We don’t have time for tests” is deliberate and reckless. “We didn’t know about that design pattern” is inadvertent and prudent. The quadrant matters because the causes of debt determine how to address it. Reckless debt needs discipline. Inadvertent debt needs learning.
Most debt accumulates through a thousand small decisions, not one dramatic shortcut. A function that does two things instead of one. A hardcoded value that should be a parameter. A missing validation that you’ll “add later.” Each one is trivial. The compound effect is a codebase where every change costs more than it should.
The AI era has fractured this metaphor into variants the classical treatment does not name. Margaret-Anne Storey has called out cognitive debt: the gap between the code that ships and the code any human actually understands. Cunningham’s debt lives in the codebase; cognitive debt lives in the people. When an agent writes a thousand lines in an afternoon and nobody reads them carefully, the codebase can look fine while the team’s understanding falls behind, and every future change has to pay interest on that gap. Addy Osmani frames a closely related problem as comprehension debt: teams now merge far more code, and far larger pull requests, than they did a year ago, while the fraction any reviewer has genuinely understood keeps shrinking. An Anthropic study of fifty-two engineers found that AI-assisted developers scored 17% lower on code-reading and debugging tasks. A 2026 analysis from CodeRabbit reported teams merging 98% more PRs at 154% larger size, with 61% of developers saying the AI output “looks correct but is unreliable.”
A third variant is specific to agentic systems. Call it agentic debt, or shadow debt: the hidden infrastructure cost of running agents at scale without a registry, observability, governance, and human-in-the-loop workflows to catch drift. JetBrains’s “shadow tech debt” framing points at the output — low-quality, architecture-blind code produced by agents that never saw the structure they were supposed to respect. Gartner projects that unmanaged AI-generated code will drive maintenance costs to roughly four times traditional levels by year two of adoption. None of this shows up in Fowler’s quadrant, because Cunningham and Fowler were describing a problem humans create for themselves. Agentic debt is a problem humans create by delegating to something that does not understand the whole.
A fourth variant lives in artifacts rather than in code or in people. Storey’s Triple Debt Model calls it intent debt: the absence or erosion of externalized rationale that the system needs to evolve safely. Cognitive debt is the gap in what humans understand. Intent debt is the gap in what’s written down about why the system is the way it is. The missing decision records, the absent design notes, the constraints that lived only in the original author’s head and left when they did. Intent debt was always corrosive, but in an agentic era it becomes acute: an agent asked to evolve a system without access to the original intent will confidently make decisions that contradict it. The repayment strategy differs from cognitive debt’s. Cognitive debt is paid down by reading. Intent debt is paid down by writing. Architecture decision records, design notes, and decision logs move the rationale out of memory and into the repository.
The Harm
Debt slows you down gradually enough that you don’t notice until it’s severe. A feature that would have taken two days in the first year of a project takes two weeks in the third year. The code hasn’t gotten harder in the abstract. It’s gotten harder because every change has to account for past compromises that were never cleaned up.
Debt also raises the risk of regressions. When code is tangled and poorly tested, changing one thing breaks another. Teams respond by changing less, which means bugs linger and features stall. The codebase becomes something people work around rather than work with. Left unchecked long enough, debt turns a codebase into a Big Ball of Mud: a system with no discernible structure where every part depends on every other part.
The hidden cost is opportunity. Every hour spent working around old hacks is an hour not spent on the feature your users actually need. Debt doesn’t just slow you down. It changes what you decide to build, because the hard things become too expensive to attempt.
Cognitive and agentic debt add a second failure mode. The classical kind slows future change. The AI-era kind can leave a codebase nobody understands, where the most confident-sounding next change is also the most dangerous one.
The Way Out
You don’t pay down debt with a single heroic rewrite. You pay it down continuously, the same way you took it on: one decision at a time.
Make debt visible. Track it explicitly. When you take a shortcut, leave a comment or a ticket that names the debt and estimates its cost. Debt you can see is debt you can prioritize. Debt you can’t see just accumulates silently. Code smells are often the first visible signal that debt has built up in an area.
Refactor as you go. The Boy Scout Rule (leave the code better than you found it) is the single most effective debt-reduction habit. You don’t need a dedicated “tech debt sprint.” You need a team that improves a small thing every time it touches a file. Rename a confusing variable. Extract a duplicated block. Add a test for the function you just had to debug.
Invest in tests for the riskiest areas. Missing test coverage is one of the most common and most expensive forms of debt. You don’t need 100% coverage. You need coverage on the code that changes often and breaks often. Tests turn risky refactoring into safe refactoring, which is the difference between debt you can pay down and debt you’re stuck with.
Apply KISS and YAGNI to stop accruing new debt. Complexity you don’t need today becomes debt tomorrow when requirements shift. Every speculative abstraction, premature generalization, and gold-plated feature is a bet that the future will look exactly like you imagine. It usually doesn’t.
Pay down cognitive debt by reading, not just refactoring. Code you haven’t read is debt no matter who wrote it. For AI-generated work, that means treating review, documentation, and architecture decision records as first-class maintenance tasks rather than chores to skip when time is tight. You can refactor a tangled function into cleanliness. You cannot refactor understanding into a team that never built it.
Pay down intent debt by writing rationale, not just code. When the why of a decision lives only in your head or in a Slack thread, the next agent (or engineer) to touch the area is operating blind. Capture intent in artifacts the next reader will actually find: ADRs in the repo, design notes alongside the code, comments that explain the constraint rather than the mechanism. An agent following well-recorded rationale produces work that fits the system. An agent guessing at unrecorded rationale produces work that contradicts it.
How It Plays Out
A startup ships its MVP in three months. The backend has no tests, the API endpoints duplicate validation logic, and the database schema has columns named temp_fix_2 and old_price_do_not_use. For the first year this doesn’t matter much. The team is small, everyone knows where the bodies are buried, and features ship fast. In year two, the team doubles. New developers break things the original team knew to avoid. A payment bug traced to duplicated validation logic costs the company a week of engineering time and a five-figure refund. The CTO proposes a rewrite. The CEO says no, because the product can’t stop shipping for three months. They compromise: 20% of each sprint goes to paying down debt, starting with the payment path. Six months later, the payment code has tests, a single validation layer, and a clean schema. The rest of the codebase is still messy, but the most expensive debt is gone.
A team uses an AI agent to add features to a two-year-old codebase. The agent is fast. It produces working code in minutes. But it follows the patterns it finds, and the patterns it finds are the accumulated shortcuts of two years. When asked to add a new notification type, the agent copies the existing notification code, including the hardcoded email templates, the duplicated user-lookup logic, and the missing error handling. The feature works. It also doubles the maintenance surface for notifications. The team realizes that pointing an agent at a debt-heavy codebase without cleanup instructions is like hiring a very fast, very literal contractor who will replicate every bad habit in the building. They change their approach: before asking the agent to add features, they ask it to refactor the area first. Extract the shared logic. Add tests. Clean up the naming. Then add the feature on the clean foundation. The agent is just as fast at refactoring as it is at feature work. The difference is entirely in what you ask it to do.
Related Patterns
Sources
Ward Cunningham introduced the debt metaphor in his 1992 OOPSLA experience report, The WyCash Portfolio Management System, comparing not-quite-right code to financial debt that incurs interest through the cost of future changes.
Martin Fowler expanded Cunningham’s metaphor with the Technical Debt Quadrant, published on his website in 2009, distinguishing deliberate from inadvertent debt and reckless from prudent debt. The quadrant gave teams a shared vocabulary for discussing different kinds of shortcuts and their appropriate responses.
Steve McConnell’s Managing Technical Debt further refined the taxonomy, distinguishing intentional debt (taken on knowingly for strategic reasons) from unintentional debt (accumulated through ignorance or neglect).
Margaret-Anne Storey’s 2026 framing of cognitive debt and intent debt extended the metaphor beyond the codebase. Cognitive debt lives in the people working on the system: the gap between code shipped and code understood. Intent debt lives in the artifacts: the gap between what the system was supposed to do and what’s recorded about why. The Triple Debt Model paper on arXiv (2603.22106, 2026) formalizes technical, cognitive, and intent debt as three distinct categories with different repayment strategies.
Addy Osmani coined comprehension debt in his March 2026 newsletter, documenting how AI-assisted teams merge more code at larger size while reviewer comprehension shrinks. He draws on Anthropic’s How AI Impacts Skill Formation study of fifty-two engineers, which found AI-assisted developers scored 17% lower on code-reading and debugging tasks, and on Faros AI’s AI Productivity Paradox analysis reporting 98% more merged PRs at 154% larger size alongside the broader trust deficit around AI output.
The New Stack’s 2026 coverage of agentic infrastructure debt catalogued the hidden costs of running agents at scale: registry, observability, governance, measurement, human-in-the-loop workflows, and sprawl management. JetBrains’s companion framing of shadow tech debt and JetBrains Central covers the output side: low-quality, architecture-blind code produced by agents operating without structural understanding. Recent coverage of the AI productivity paradox and AI-generated-code maintenance cost rounds out the agentic-debt literature.