How I Think About Technical Debt in High-Velocity Teams

· 5 min read

How I Think About Technical Debt in High-Velocity Teams

Technical debt gets a bad reputation. Engineers talk about it like it's something that should never exist, a sign of poor engineering or rushed decisions. But debt in software, like debt in finance, is a tool. The question isn't whether to take on debt. It's whether you're taking on the right debt, consciously, with a plan to pay it back.

The Three Types of Tech Debt

Deliberate Debt

You know the code isn't ideal. You ship it anyway because the trade-off makes sense.

"We're hardcoding this for US-only because we launch in the US next month. We'll internationalize when we expand to Europe in Q3."

This is healthy. It's a conscious decision with a clear payback timeline. Write it down. Put a TODO with context. Make it visible.

Accidental Debt

You didn't know there was a better way. You learned something new, and now the old code looks wrong.

This is inevitable and isn't anyone's fault. The codebase reflects the team's understanding at the time it was written. As the team learns, the gap between what they know now and what the code reflects grows.

Environmental Debt

The world changed. A library was deprecated. An API was sunset. The Android platform introduced a new way of doing things. Your code was fine when you wrote it. Now it's outdated.

This is the sneakiest kind because nobody made a bad decision. The ground shifted.

How I Categorize and Prioritize

I use a simple framework: impact vs effort, mapped against urgency.

High Impact, Low Effort:   Do it now. These are quick wins.
High Impact, High Effort:  Plan it. Put it on the roadmap.
Low Impact, Low Effort:    Do it when you're in the area.
Low Impact, High Effort:   Don't do it. Accept it.

The mistake most teams make is treating all tech debt as equally important. A naming inconsistency and a data race are both "tech debt," but one of them will cause a production incident and the other won't.

The Debt Register

I maintain a lightweight list of known tech debt. Not a detailed doc. Just a list with three columns:

| What                              | Risk Level | When to Pay     |
|-----------------------------------|------------|-----------------|
| Feed cache has no TTL             | High       | Before scaling  |
| Logger uses string concatenation  | Low        | Never (harmless)|
| Auth tokens stored in SharedPrefs | Medium     | Q2 security push|
| Old Retrofit 1.x client wrapper  | Low        | Next API change |

When someone asks "should we fix this?" I check the register. If the risk is low and nobody is actively working in that area, the answer is usually "not now."

Paying Down Debt in a Fast-Moving Team

On high-velocity teams, you can't stop shipping features to refactor. And you shouldn't. Here's how I integrate debt paydown into feature work:

The Boy Scout Rule. Leave the code a little better than you found it. Not a lot better. A little. Rename that confusing variable. Extract that duplicated logic. Add that missing null check. Small improvements that take minutes, not hours.

Bundle debt paydown with related features. If you're building a new feature that touches the auth system, and the auth system has known debt, this is the time to address it. You're already in the code. You already have context. The incremental cost is low.

Dedicate 10-15% of sprint capacity. Not a "tech debt sprint." Not a quarterly cleanup. A consistent allocation every sprint. This prevents debt from accumulating to the point where it requires a dedicated effort.

When to Say No

Some tech debt isn't worth paying down. The code works. It's ugly but correct. Nobody needs to change it. The cost of refactoring exceeds the benefit.

I've seen teams spend weeks rewriting a "messy" module that was stable, well-tested, and rarely modified. The rewrite introduced new bugs. The old code was fine. It just didn't match the team's current style preferences.

Aesthetic debt is not real debt. If the code works, is tested, and doesn't need frequent changes, leave it alone. Your time is better spent elsewhere.

The Real Cost of Ignoring Debt

The cost isn't the debt itself. It's the interest. Every new feature built on top of unaddressed debt takes longer to build, is harder to test, and is more likely to have bugs.

When a team says "we move slower than we used to," it's usually compounded interest from years of untracked debt. The individual decisions were all reasonable. The accumulated effect is a codebase where everything is harder than it should be.

Track the debt. Pay it down steadily. Don't let it compound.

Related Posts