Technical Debt
debt(d7/e7/b7/t5)
Closest to 'only careful code review or runtime testing' (d7). Tools like phpstan, phpcs, phpmd, and phploc can surface symptoms (complexity, style violations, lack of tests), but they measure proxies, not debt itself. Unacknowledged or undocumented debt — especially architectural shortcuts — remains invisible until a developer manually audits the codebase or pain accumulates in production. The detection is inferential rather than direct.
Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix is framed at the process/tracking level ('add to backlog with business framing'), but actual remediation of accumulated technical debt typically spans multiple files, components, and sometimes architectural layers. The common_mistakes warn about 'debt sprints' not addressing root causes, implying debt repayment is rarely a localised fix and often requires sustained cross-cutting effort across the codebase.
Closest to 'strong gravitational pull' (b7). Technical debt applies across web, cli, and queue-worker contexts (all PHP contexts), and the term's own metadata notes it 'compounds like financial debt' — every future change is shaped and slowed by existing debt. Debt in critical paths costs the most (common_mistakes), meaning it exerts gravitational pull on high-change areas, making every new feature harder and every refactor riskier over time.
Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The canonical misconception is explicit: developers believe technical debt is always bad and must be eliminated, when in reality deliberate, time-bounded debt is a legitimate business decision. The trap is treating all shortcuts as equivalent — conflating managed debt with untracked debt. This is a well-documented industry gotcha that most developers encounter and eventually correct, but it causes real misalignment between engineering and business teams until learned.
Also Known As
TL;DR
Explanation
Technical debt (Ward Cunningham's metaphor) describes the future work created by making expedient rather than optimal decisions. Like financial debt, small amounts can be strategic, but unmanaged debt compounds — each shortcut makes the codebase harder to change, slowing future development. Debt quadrants include: deliberate/prudent (known shortcuts), deliberate/reckless (cowboy coding), inadvertent/prudent (best practices evolved), and inadvertent/reckless (ignorance). Track debt explicitly, allocate time to pay it down, and never let it accumulate silently.
Common Misconception
Why It Matters
Common Mistakes
- Not tracking technical debt explicitly — unacknowledged debt is not managed or prioritised.
- Treating all debt as bad — deliberate, time-bounded shortcuts are sometimes the right business decision.
- Declaring 'debt sprints' without addressing root causes — debt that isn't tracked will return.
- Allowing debt to accumulate in critical paths — debt in high-traffic, high-change code costs the most.
Avoid When
- Using technical debt as an excuse to never refactor — debt must be actively managed, not accumulated indefinitely.
- Taking on debt without documenting it — undocumented debt is invisible and never gets paid back.
- Treating all shortcuts as debt — pragmatic decisions with known trade-offs are intentional, not debt.
When To Use
- Deliberately when a deadline requires shipping quickly and there is a clear plan to repay the debt.
- Tracking debt in a backlog with concrete remediation tasks — visibility is the first step to repayment.
- Debt budgets — allocate a percentage of each sprint to debt reduction to prevent accumulation.
- Before major feature work on a debt-laden area — pay the debt first or the feature will be harder.
Code Examples
// Deliberate but untracked debt — no ticket, no owner, no deadline:
function calculateTax(float $amount): float {
// TODO: implement real tax logic
return $amount * 0.2; // Hardcoded UK VAT — breaks for non-UK customers
// No ticket linked, no one knows this exists
}
// Document debt explicitly — make it visible and trackable
// In code:
// TODO(2024-Q2): Replace O(n²) sort with priority queue (TICKET-1234)
// FIXME: Silently swallows errors — TICKET-5678
// In tech-debt.md:
# Technical Debt Register
## High Priority
- [ ] Split god class OrderManager into focused services (est. 5d)
- [ ] Replace raw PDO in UserRepository with typed query builder (est. 3d)
// PHPStan baseline — acknowledges existing debt, blocks new regressions:
$ vendor/bin/phpstan analyse --generate-baseline
# Baseline suppresses current errors; NEW errors still fail the build