PushBackLog

Technical Debt Management

Soft enforcement Complete by PushBackLog team
Topic: management Topic: quality Topic: planning Skillset: management Skillset: engineering Technology: generic Stage: planning Stage: execution

Technical Debt Management

Status: Complete Category: Management Default enforcement: Soft Author: PushBackLog team


Tags

  • Topic: management, quality, planning
  • Skillset: management, engineering
  • Technology: generic
  • Stage: planning, execution

Summary

Technical debt is the accumulated cost of design and implementation decisions that optimise for short-term delivery at the expense of long-term maintainability. It is not inherently bad — deliberate technical debt taken consciously is a legitimate trade-off. Unmanaged technical debt, allowed to accumulate without visibility or plan, compounds interest until it dominates the cost of adding features and increases the risk of defects.


Rationale

Every software system accumulates technical debt. Teams that do not actively manage it are not avoiding it — they are accumulating it invisibly until it forces itself into visibility through slowdowns, outages, or inability to deliver.

Managed technical debt is a business conversation. Unmanaged technical debt is an operational surprise. Making debt visible, classifying it, and tracking paydown enables engineering teams to have honest conversations with product and business stakeholders about the cost of previous shortcuts and the value of remediation work.


Guidance

Debt taxonomy

Not all technical debt is the same. Classify debt to prioritise it:

TypeDescriptionUrgency
Deliberate-reckless”We know this is wrong; we don’t have time to fix it properly”High — fix ASAP
Deliberate-prudent”We’ll ship now and refactor when we understand this domain better”Medium — schedule
Inadvertent-recklessIntroduced without knowing it was wrong (missing tests, poor naming)Depends on impact
Inadvertent-prudentGood design at the time; requirements evolved beyond itLow — address opportunistically

The Fowler/Cunningham quadrant provides this taxonomy. Understanding the origin of debt clarifies who owes the debt and whether it was a reasonable trade at the time.

The technical debt register

A technical debt register is a tracked list of known debt items with enough information to prioritise them. A minimal register entry:

FieldDescription
TitleShort description of the debt item
LocationWhich component, service, or file is affected
TypeDeliberate / inadvertent, reckless / prudent
ImpactWhat problems does carrying this debt cause?
EffortRough estimate of paydown cost
OwnerWho is accountable for addressing it
PriorityBased on impact × carrying cost

The register lives in the team’s backlog tooling, not in a spreadsheet that no one reads.

Paydown strategies

Debt paydown should be scheduled, not heroic:

  • Boy Scout Rule — leave code better than you found it; address small debt items as part of feature work when the code is open
  • Dedicated capacity — allocate a percentage of sprint capacity to debt work (10–20% is a common starting point)
  • Debt sprints — periodic sprints focused on debt for systems where it has accumulated to a critical level
  • Strangler fig — incrementally replace a problematic component behind an interface boundary rather than a “big bang” rewrite

Rewrites should be approached with caution. Full rewrites of large systems rarely deliver on their promise and introduce new debt while the old system is still running.

Making debt visible to stakeholders

Technical debt must be communicated in business terms:

  • “This module has no tests; every change takes three times longer than comparable modules and releases have a 4× higher defect rate”
  • “Our deployment pipeline takes 45 minutes; competitor teams deploy in 8 minutes; we lose approximately N developer-hours per sprint waiting for CI”

Frame debt as a carrying cost — an ongoing tax on delivery — rather than an abstract engineering concern.


Common failure modes

FailureDescription
Invisible debtNo register; debt accumulates until it is discovered through incidents
Zero tolerance cultureAll debt framed as shameful; teams hide it; no space to address it
Debt-only sprints that never happenTeam promises to “do a cleanup sprint next quarter”; it never arrives
Rewrites instead of paydownLarge rewrites attempted to escape debt; new system reintroduces it
No stakeholder visibilityEngineering knows about the debt; product and business do not; prioritisation battles are lost

Examples

Tech-debt register entry

## TD-047 — Authentication service uses deprecated `jsonwebtoken` v8 signing API

**Category**: Dependency / Security  
**Discovered**: 2024-08-12  
**Severity**: High  
**Estimated effort**: 1 day

**Symptom**  
The auth service uses `jwt.sign(payload, secret, callback)` with the v8 callback API. `jsonwebtoken` v9 removes this form; the library also had two CVEs (CVE-2022-23539, CVE-2022-23541) patched only in v9+.

**Impact if left**  
- Known JWT validation vulnerabilities remain in production  
- Upgrading past v8 later will be a larger breaking change as other callers may accumulate

**Proposed resolution**  
Upgrade `jsonwebtoken` to `^9.0.0`; migrate two call sites from callback to synchronous `jwt.sign()`; update unit tests.

**Owner**: @todd  
**Target sprint**: Sprint 28

Linking debt to work: the “boy scout” pattern in a PR

## What this PR does
Refactors the invoice service to use the repository pattern.

## Debt addressed
This resolves TD-031 (service layer directly querying the database, making unit tests impossible without a live DB). As per team norms, the refactor is scoped to the files changed for the feature — no unrelated files changed.

## Debt introduced
None introduced. The migration script in `scripts/migrate-invoices.ts` is deleted after use; no new long-term debt.

Debt ratio in sprint planning

Sprint 28 capacity: 40 points

Allocation:
  Features / stories   32 points (80%)
  Debt repayment        8 points (20%)
    └ TD-047: jsonwebtoken upgrade           2 pts
    └ TD-038: Remove feature flag residue    3 pts
    └ TD-029: Replace hand-rolled CSV parser 3 pts

Debt register before sprint: 27 items
Debt register after sprint (projected): 24 items

Maintaining the 20% floor means the register shrinks over time even as normal delivery introduces new items.



Part of the PushBackLog Best Practices Library. Suggest improvements →