All posts

The hidden cost of technical debt

Technical debt is not just slow feature development. Here is how to quantify it, communicate it to stakeholders, and actually pay it down.

“Technical debt” has become one of those phrases that engineering teams use to explain slowness to non-technical stakeholders, and that non-technical stakeholders have learned to discount. That’s a problem, because real technical debt has real costs — and those costs compound.

What technical debt actually is

Ward Cunningham coined the term as a deliberate metaphor: like financial debt, technical shortcuts taken today incur interest over time. The interest is paid in the form of extra work every time you touch the affected code.

The problem is that the term now gets applied to everything from a missing test to an unmaintainable five-year-old monolith. These are not the same thing. Calling them both “technical debt” loses the signal.

A more useful frame: friction cost. Every time a developer touches a part of the codebase, how much extra time does the state of that code add? An hour? A day? Does it require tribal knowledge that only one person has?

How to quantify it

You don’t need perfect numbers. You need enough signal to make decisions.

Start by asking your engineering team to score the most-touched parts of the codebase on two axes:

  • Change frequency: how often does this code change?
  • Pain level: how hard is it to change safely?

High frequency + high pain is where you focus. That intersection is where debt is actively costing you velocity on features that matter.

Communicating it to stakeholders

The language that works: translate friction into time, and time into money.

“Our payment service is poorly understood by the team and has no integration tests. Every change to it takes two to three days longer than it should and has caused three production incidents this year. Cleaning it up is a two-week investment that will save roughly one engineer-week per month going forward.”

That’s a business case. “We have technical debt in the payments module” is not.

Paying it down without stopping everything

The two common mistakes are: doing nothing until the debt is catastrophic, or stopping all feature work for a “big rewrite” that takes twice as long and ships half of what was planned.

The practical middle path:

  1. The boy scout rule: leave every file you touch slightly better than you found it. Rename a confusing variable. Extract a function. Add a test for the path you just validated manually.
  2. Scheduled debt sprints: one week per quarter dedicated entirely to reducing friction in the highest-pain areas.
  3. No rewrites — only replacements: replace one component at a time, running old and new in parallel until the new one is proven.

Debt reduction is continuous, not a project.