The most dangerous technical debt is the debt you don't know you have. Teams that can't measure their debt can't prioritise it, can't justify investment in it, and can't track whether they're making progress.
Measuring technical debt is hard because it's multi-dimensional — it spans code, architecture, infrastructure, testing, documentation, and dependencies. No single metric captures it all. But a combination of quantitative metrics and qualitative signals gives you an accurate picture.
Quantitative Metrics
Code Complexity
Cyclomatic complexity measures the number of independent paths through a function. High complexity = hard to understand, test, and modify.
| Score | Interpretation | Action |
|---|---|---|
| 1-10 | Simple, low risk | None needed |
| 11-20 | Moderate complexity | Monitor, consider refactoring |
| 21-50 | High complexity | Schedule refactoring |
| 50+ | Untestable, high risk | Urgent refactoring required |
Tool: SonarQube, CodeClimate, or language-specific tools (radon for Python, gocyclo for Go).
Where to focus: Don't measure average complexity across the codebase — that's a vanity metric. Focus on hotspots: files with high complexity AND high change frequency. These are the areas where debt has the most impact.
Test Coverage
Test coverage measures the percentage of code exercised by automated tests. Low coverage means changes are made without safety nets.
| Coverage | Interpretation |
|---|---|
| 0-20% | Critical — changes are essentially untested |
| 20-50% | Low — significant risk of undetected bugs |
| 50-70% | Moderate — core paths are tested |
| 70-85% | Good — most code is tested |
| 85%+ | Excellent — focus on critical path coverage, not 100% |
Important nuance: Coverage measures quantity, not quality. 80% coverage with meaningless assertions is worse than 50% coverage with thorough tests. Use mutation testing (Stryker, PITest) to measure test quality.
Dependency Health
| Metric | How to Measure | Red Flag |
|---|---|---|
| Dependencies with known CVEs | Snyk, OWASP Dependency-Check | Any critical/high CVE |
| Dependencies > 2 major versions behind | Renovate, Dependabot | > 20% of dependencies |
| Deprecated dependencies | Manual review + tool scanning | Any deprecated dependency |
| Unmaintained dependencies (no commits in 2+ years) | GitHub activity check | Any critical dependency unmaintained |
Build and Deploy Metrics
| Metric | Measurement | Debt Signal |
|---|---|---|
| Build time | CI/CD pipeline duration | > 15 minutes indicates build system debt |
| Flaky test rate | Test failures without code changes | > 2% flaky rate indicates test debt |
| Deployment frequency | DORA metrics | Decreasing frequency = growing debt |
| Change failure rate | DORA metrics | Increasing rate = quality/testing debt |
Code Churn Analysis
Code churn measures how frequently files change. When combined with complexity, it reveals the most impactful debt:
High churn + High complexity = Critical debt. These files change frequently and are the hardest to change correctly. They're the highest-priority debt reduction targets.
High churn + Low complexity = Healthy code. Frequently changed but easy to modify. No action needed.
Low churn + High complexity = Latent risk. Not a problem today, but will be when the code needs to change. Monitor.
Tool: Code Maat, git log analysis, or LinearB/Sleuth.
Qualitative Signals
Developer Friction Survey
Conduct a quarterly survey (15-20 questions) asking developers about their experience:
Key questions:
- "Which areas of the codebase are you most reluctant to change? Why?"
- "How much time per week do you spend on tasks caused by technical debt?"
- "What's the #1 thing that slows down your daily work?"
- "If you could fix one thing about our codebase, what would it be?"
- "Rate the quality of our test suite (1-5)"
- "Rate the quality of our documentation (1-5)"
- "How confident are you that a change you make won't break something unexpected? (1-5)"
Processing results: Aggregate responses, identify patterns, and prioritise the most commonly cited pain points.
Onboarding Time
Track how long it takes new developers to make their first meaningful contribution:
| Onboarding Time | Interpretation |
|---|---|
| Under 1 week | Excellent — good documentation, clear codebase |
| 1-2 weeks | Good — some learning curve is normal |
| 2-4 weeks | Concerning — documentation or code clarity debt |
| Over 1 month | Critical — significant knowledge silo or code quality issues |
Incident Analysis
Review incident post-mortems for root causes related to technical debt:
- "The bug was in code that has no tests"
- "The failure cascaded because services are tightly coupled"
- "We couldn't deploy the fix quickly because the deployment process is manual"
- "We didn't detect the issue because monitoring is incomplete"
Track the percentage of incidents attributed to technical debt. If it's above 30%, debt is a reliability problem, not just a velocity problem.
The Technical Debt Dashboard
Build a dashboard that combines quantitative and qualitative signals:
| Metric | Current | Trend | Target | Status |
|---|---|---|---|---|
| High-complexity hotspots | 23 files | ↑ +3 | < 15 | Red |
| Test coverage (critical paths) | 62% | ↑ +5% | > 80% | Amber |
| Dependencies with CVEs | 4 high, 12 medium | ↓ -2 | 0 high, < 5 medium | Amber |
| Build time (p50) | 11 min | → stable | < 8 min | Amber |
| Developer friction score | 3.2/5 | ↑ +0.2 | > 4.0 | Amber |
| Onboarding time | 3 weeks | → stable | < 2 weeks | Red |
| Debt-related incidents (%) | 35% | ↓ -5% | < 15% | Red |
Translating to Executive Language
Executives don't care about cyclomatic complexity. They care about speed, cost, risk, and talent.
Speed: "Technical debt has increased our average feature delivery time by 40% over the past year. Features that took 2 weeks now take 3.5 weeks."
Cost: "We estimate $X in engineering capacity is consumed by debt-related work annually. That's Y features we're not building."
Risk: "35% of our production incidents are caused by technical debt. Each incident costs an average of $Z in engineering time and customer impact."
Talent: "Two of our last three departing engineers cited codebase quality as a factor. Replacing each costs $200K+ in recruiting, onboarding, and lost productivity."
Measuring technical debt is the first step to managing it. If you need help establishing a debt measurement programme, let's talk.