"We don't have tech debt." Come on, I know you're lying.
I have heard this line for more than a decade.
"We're fine. We don't really have tech debt."
Usually right before:
- a "one-day change" turns into a week
- production incident reveals nobody understands one critical flow
- the team touches one old module like it is a landmine
That is tech debt.
And no, it is not just old libraries.
One founder told me this on a Tuesday.
By Friday, their "tiny change" broke billing in one edge case nobody remembered existed.
Again: working software can still be debt-ridden software.
Tech debt is not one thing
Most teams reduce it to dependency hygiene:
- old packages
- outdated framework versions
- TODO comments from three product managers ago
That is real debt. No debate there.
But the uglier debt is usually invisible:
- what the team no longer understands
- what was never documented
- what AI generated in 20 minutes and nobody really internalized
The invisible debt compounds faster than package updates.
The debt everyone sees: dependencies
Yes, this one is real:
- old libraries
- unsupported versions
- security vulnerabilities
- "we will upgrade later"
It is visible, measurable, and easy to plan.
The trap is obvious: people fix what they can count.
So they count CVEs, version gaps, stale libs.
Meanwhile, architecture drifts and team understanding erodes quietly in the background.
The debt that drains velocity: architecture
This appears when local shortcuts slowly kill global coherence.
Symptoms:
- duplicate logic across services
- unclear module boundaries
- "temporary" integrations that became permanent
- coupling nobody planned
Code still compiles. Features still ship.
But every next change costs more negotiation, more regression risk, more fear.
I have seen teams with "clean code" and broken architecture.
Nice functions. Painful delivery.
If your team says "it's just one more exception" every sprint, you are already paying architecture interest.
The debt that bites after people leave: knowledge
Knowledge debt is the gap between how the system behaves and how much the team truly understands.
Examples:
- critical flow understood by one person only
- business rules trapped in Slack, Notion, and memory
- onboarding takes months, not weeks
- people are afraid to refactor because they cannot predict side effects
You are not blocked by code.
You are blocked by missing shared understanding.
When one senior leaves and velocity drops by 40%, that is not a hiring problem first.
That is knowledge debt coming due.
The debt nobody logs: decisions
Every system is a graveyard of old trade-offs.
When trade-offs are not recorded, the team keeps re-deciding the same problems:
- "Why did we choose this queue?"
- "Why not event-driven here?"
- "Was this endpoint intentionally synchronous?"
Without lightweight ADRs or any decision log, context evaporates.
Then teams confuse old constraints with current reality.
Same debates, new sprint, same confusion. That is decision debt.
One classic smell: two senior engineers debating a decision from six months ago, both confident, both wrong, because the original constraints changed and nobody wrote them down.
AI did not invent debt. It boosted the throughput.
AI did not create technical debt.
It made the debt pipeline faster.
Today you can generate more code in one week than some teams used to write in a month. Great.
But understanding still moves at human speed.
So we get:
- more code created
- less time spent on internals
- less architectural reflection
- faster context decay
AI increases throughput. It also increases the amount of code the team only "kind of" understands.
If you generate faster than you absorb, debt accumulates in the understanding layer first, and in production behavior later.
That is why teams can look "productive" and fragile at the same time.
The dangerous myth: "If it works, we're fine."
Working software is not healthy software.
A lot of debt stays hidden until:
- a new integration arrives
- traffic doubles
- team composition changes
- incident response requires knowledge nobody has
By then, paying that debt is much more expensive.
What to do instead (pragmatic version)
You do not need a 6-month "tech debt transformation program."
You need boring engineering discipline.
Start with this:
- Track debt by type, not as one generic backlog label.
- Add one architecture checkpoint per sprint.
- Write short ADR notes for non-trivial decisions (really short, but written).
- Review for understandability, not only correctness.
- For AI-generated code, review boundaries, intent, and tests harder than usual.
Small process upgrades beat heroic cleanup projects every time.
Final thought
Most teams do not drown because npm is outdated.
They drown because system understanding fades while change volume grows.
Especially now, with AI.
So next time someone says, "We don't have tech debt," ask two questions:
Do we have current dependencies?
Good.
Do we still understand the system we are shipping?
If the second answer is "mostly" or "kind of," you have debt.
You just have not paid interest yet.
If this sounds familiar, do a quick audit with your team this week:
- Where are we carrying dependency debt?
- Where are we carrying architecture debt?
- What part of the system is "known" by one person only?
If those answers are uncomfortable, good.
That is where your next engineering win is.


