What Causes Technical Debt

ModernLift · ·12 min read
Part 3 of 13

Technical debt has seven recurring causes: schedule and business pressure, evolving requirements, deferred maintenance and aging dependencies, knowledge loss as people leave, missing tests and weak feedback, low standards or skill gaps, and entropy from accumulated change. Some are choices you control. Others are inherent to building software over time.

Part 2 named the six places debt lives. This part asks where it comes from, because the cheapest debt to deal with is the debt you never take on, and you cannot prevent a force you have not named. Understanding cause also corrects the most common misdiagnosis: that technical debt is a sign of careless engineers. Most debt is structural. It would accumulate on a team of excellent people working under the same pressures, which is precisely why blaming individuals prescribes the wrong fix.

There are seven recurring causes. The first thing to recognize is that they are not equally within your control. Some are choices. Some are inherent to building software that survives contact with reality. Sorting them is the point.

1. Schedule and business pressure

The most common cause, and the one closest to a genuine decision. A date is fixed, whether a launch, a contract, or a board commitment, and the better solution will not fit inside it, so the team ships the expedient one. Part 1 established that this can be entirely rational: borrowing to hit a deadline that has real value is leverage used well.

It turns destructive in two ways. First, when the borrowing is never recorded, so the repayment is never scheduled and the “temporary” shortcut becomes load-bearing. Second, when deadline pressure is constant. When every sprint is an emergency, the team is always borrowing and never repaying, and the debt compounds with no quarter that funds paying it back. The cause here is less any single deadline than an operating rhythm that has no room for repayment.

2. Evolving requirements

This cause is unavoidable, and naming it matters because it absolves so much apparent “bad design.” A system is designed against the understanding available at the time. Then the business changes, the market moves, a use case nobody anticipated becomes central, and the design that was correct for the original requirements is now wrong for the actual ones. That gap is debt, and no amount of foresight would have prevented all of it.

This is Fowler’s inadvertent-prudent debt: “now we know how we should have done it.” You cannot design for requirements you do not yet have. The failure is not incurring this debt. It is refusing to revisit a design once the requirements that shaped it have plainly moved on.

3. Deferred maintenance and aging dependencies

Some debt accrues from doing nothing at all. Libraries fall behind, runtimes reach end of life, the database version ages past its support window. This is the dependency debt of Part 2, viewed as a cause. The system did not get worse. The world moved and the system stayed still.

This cause is partly unavoidable, since everything ages, and partly a choice, since you decide whether to upgrade on a cadence or to defer. Deferral is where it compounds. Each skipped upgrade makes the next one a larger jump across more breaking changes, until what would have been routine becomes a project. The interest here is mechanical and patient, and then suddenly not. It arrives as a security finding or a withdrawn vendor support contract.

4. Knowledge loss

People leave, and they take with them the why. This is the knowledge debt of Part 2 as an active force, the single most under-tracked cause of debt there is, because nothing in the code changes when it happens. The billing logic still runs. It is just that no one alive can now say why it rounds the way it does.

The data makes this concrete and urgent. IBM (reported via Fujitsu, 2020) reports the average COBOL developer is roughly 58, with about 10% of the COBOL workforce retiring each year. That is a steady, scheduled conversion of living knowledge into archaeological debt. The cause is not the leaving, since people will always leave, but the failure to capture what they knew while they were still there to ask. It is the most preventable expensive debt and the most commonly neglected.

5. Missing tests and weak feedback

When a team cannot quickly and reliably tell whether a change broke something, two things follow. Changes are verified slowly and by hand, and the safety net for fixing debt is absent, so debt that could be refactored away never is. This is the test debt of Part 2 acting as a cause of all the others. It is the force multiplier.

It pairs catastrophically with cause 1. Deadline pressure removes the time to do it right. Missing tests remove the ability to safely fix it later. Together they convert a temporary shortcut into a permanent fixture, because there is neither room to avoid it now nor confidence to repair it afterward. This combination, pressure plus no tests, produces more lasting debt than either does alone.

6. Low standards or skill gaps

This is the cause people reach for first, and it is usually smaller than they think. Inconsistent standards, no code review, unfamiliarity with the domain or the language, a team that genuinely does not know a better pattern exists. This is Fowler’s reckless-inadvertent quadrant, the “what’s layering?” case.

It is real, and it is worth addressing through review, standards, and learning. But it is one cause among seven, and treating it as the cause leads straight to the misdiagnosis this article opened with: blaming the people, when the structural forces above would generate debt under any team. Excellent engineers under cause 1 with cause 5 produce plenty of debt. Skill is a factor, not the factor.

7. Entropy from accumulated change

The last cause is the most fundamental and the most unavoidable. A system that is changed thousands of times over many years drifts toward disorder, regardless of how disciplined each individual change was. Every modification is locally reasonable. The sum of ten thousand reasonable modifications is a structure no one designed and no one fully understands.

This is the software equivalent of the second law of thermodynamics. It is why even a well-run system eventually accumulates debt, why “we just need to be more careful” is not a complete answer, and why systems have a natural tendency to slide toward legacy absent deliberate counter-effort. You do not prevent entropy. You spend energy continuously to hold it back, which is what active debt management is.

The technical debt quadrant

The seven causes answer “where did it come from.” Martin Fowler’s technical debt quadrant answers a second question that matters just as much: was it a choice or an accident, and was it reasonable or careless. The two axes are deliberate versus inadvertent and reckless versus prudent.

RecklessPrudent
Deliberate“We do not have time for design.”“We must ship now and handle the consequences later.”
Inadvertent“What is layering?”“Now we know how we should have done it.”

The quadrant maps onto the causes cleanly. Deliberate-prudent debt is cause 1 used well, a recorded decision to ship now and repay later. Deliberate-reckless is cause 1 abused, cutting corners with no intent to record or repay. Inadvertent-reckless is cause 6, the skill and standards gap where the team did not know better. Inadvertent-prudent is cause 2, the debt you could only see once the requirements moved. The single most useful thing the quadrant does is separate the debt worth preventing, the reckless column, from the debt worth managing, the prudent column. The goal was never zero debt. It was zero reckless debt.

Controllable, manageable, inherent

The seven causes sort onto a spectrum, and the sorting is the actionable part:

CauseHow much control you have
Schedule & business pressureLargely controllable: record and schedule deliberate debt
Missing tests & weak feedbackLargely controllable: invest in the safety net
Low standards / skill gapsControllable: review, standards, learning
Knowledge lossManageable: capture understanding before people leave
Deferred maintenanceManageable: upgrade on a cadence, not in a panic
Evolving requirementsInherent: manage by revisiting design as needs move
Entropy of accumulated changeInherent: manage with continuous, deliberate effort

The lesson is not “prevent all debt.” Three of the seven causes are inherent to building software that lasts, and fighting them to zero is wasted energy that produces its own paralysis. The lesson is to prevent the avoidable, the reckless and unrecorded debt from pressure, missing tests, and skill gaps, and to take on the unavoidable deliberately, with a record and a repayment plan. That is the difference between a system that ages gracefully and one that slides into legacy.

How to tell which cause is at work

A taxonomy is only useful if you can point it at your own system. Work backward from what you observe.

What you observeLikely cause
“Temporary” workarounds that are years oldSchedule pressure, never recorded (1)
The design fights every new feature you addRequirements outran the original design (2)
Upgrades are dreaded and breaking changes pile upDeferred maintenance and aging dependencies (3)
No one can explain why a rule behaves the way it doesKnowledge loss (4)
Every change needs slow, manual verificationMissing tests and weak feedback (5)
Patterns are inconsistent across the codebaseLow standards or skill gaps (6)
Each part is fine but no one understands the wholeEntropy of accumulated change (7)

Real debt rarely traces to one row. Consider a billing module that shipped under a hard contract date with a thin test suite, then lost the engineer who wrote its proration logic, and then met a tax rule its original design never anticipated. That is causes 1, 5, 4, and 2 braided into a single module everyone now fears to touch. No individual decision was reckless. The compounding is what makes it expensive, and it is why the fix is a change in how you work, not a name to blame.

A caution on hindsight

Diagnosing cause is genuinely hard after the fact, and there is a real risk of tidy hindsight: every piece of debt gets a clean story about why it happened, and the story is often a guess. The seven causes are a checklist for thinking and for prevention going forward, not a forensic tool for assigning blame to past decisions. Most debt has several causes braided together, and the people involved were usually doing the best they could with the information and the deadline they had. If a cause analysis is producing blame rather than a list of things to change in how you work, it has gone wrong.

Where this leads

We have now defined debt, located it, and traced where it comes from, the full TOFU picture. The question a technical leader actually has to answer, though, is not “what is technical debt?” but “what is ours costing us, and is it worth paying down?” That requires turning an abstract liability into a number the business will act on. Part 4, The True Cost of Technical Debt, makes the cost concrete, covering the visible interest, the hidden costs, and the sourced industry figures that put a credible scale on the problem.

Frequently asked questions

What is the most common cause of technical debt?
Schedule and business pressure is the most common single cause: shipping the expedient solution to hit a date. But it rarely acts alone. The most damaging debt usually comes from the combination of deadline pressure and missing tests, which removes both the time to do it right and the safety net to fix it later, so the shortcut becomes permanent.
Is technical debt caused by bad developers?
Rarely. Most debt is structural, not a skill failure. It comes from deadline pressure, requirements that changed after the design was set, dependencies aging out, and knowledge leaving with people. Blaming individuals misdiagnoses the cause and so prescribes the wrong fix. Skill gaps are one of seven causes, and usually not the largest.
Is all technical debt bad?
No. Deliberate, well-reasoned debt taken to hit a deadline that has real value is a legitimate tradeoff, the same way financial leverage is. It only turns bad when it is never recorded and never repaid, so a temporary shortcut quietly becomes load-bearing. The debt worth eliminating is the reckless, unrecorded kind. The debt worth managing is the deliberate kind you took on with a plan.
How do you tell which cause is behind your technical debt?
Work backward from the symptom. Years-old "temporary" workarounds point to unrecorded schedule pressure. A design that fights every new feature points to requirements that moved. Dreaded upgrades point to deferred maintenance. Rules nobody can explain point to knowledge loss. Slow manual testing points to a missing safety net. Most real debt has several of these braided together, so the goal is a list of things to change, not a single culprit.
Can technical debt be prevented entirely?
No, and trying to is its own mistake. Some causes, such as evolving requirements, dependency aging, and the entropy of accumulated change, are inherent to building software that lasts. You can only manage them, not eliminate them. The goal is to prevent the avoidable, reckless debt and to take on the unavoidable debt deliberately, with a record and a repayment plan.
All 13 parts of Technical Debt: Measure It, Price It, Pay It Down →