Comprehension debt is worse than code debt
Code debt makes change expensive. Comprehension debt makes change unsafe, and the real cost is not the hours you spend but the changes you quietly stop attempting.
Every technical debt conversation I have sat in for fifteen years has been about hours. This module is ugly, so the next change here takes three days instead of one, so here is the interest payment, so here is the case for refinancing. It is a good model. It has the enormous advantage of being expressible in a currency finance understands.
It also does not describe the thing that is now accumulating, and the mismatch matters more than it sounds.
My position: comprehension debt, the code in your system that nobody currently understands, is a strictly worse liability than ordinary code debt, and the reason is not that it costs more hours. It is that it changes what your team is willing to do at all.
Code debt taxes change. Comprehension debt forbids it.
Ordinary technical debt is a tax. It is annoying, it is quantifiable, and crucially it is payable. You know the messy module is messy, you know roughly what it does, and when the business needs a change there you grit your teeth, budget three days instead of one, and ship.
Comprehension debt does not present a bill. It presents a risk of unknown magnitude, and organisations do not handle those by paying them. They handle them by avoiding them.
The observable behaviour is a team that quietly routes around a subsystem. A feature request arrives that would naturally live in module A, and instead it gets implemented in module B with an adapter, because nobody wants to open A. Nobody decides this. It emerges from a series of individually reasonable estimates, each one padded by the person who would have to do the work, until the padding makes the natural design lose to the unnatural one.
Six months later you have a system whose architecture reflects your team’s fear map rather than its domain.
Code debt
- Bills you in hours
- Cost is roughly predictable
- Shows up in estimates
- Payable by refactoring
- Everyone can point at it
Comprehension debt
- Bills you in declined options
- Cost is a variance, not a mean
- Shows up as a change of plan
- Not payable by refactoring at all
- Invisible: the code reads fine
It compounds where code debt amortises
Ordinary debt has a natural ceiling. A messy module gets touched, and when it gets touched someone cleans a corner of it, or at minimum re-reads it and reconstructs a mental model. Contact with the code is self-limiting on ignorance. That is why the very worst code in most codebases is not in the busiest files.
Comprehension debt runs the other way. The less you understand a region, the less willing you are to touch it, and the less you touch it the less you understand it. It is a positive feedback loop with no natural damping, and the only thing that used to break it was staff turnover forcing someone new to go in and learn.
Now the loop has an accelerant. With something like 41 percent of production code AI-generated by early 2026, the volume arriving is no longer bounded by anyone’s reading rate. The gap opens continuously, without a single resignation, and there is no moment at which anybody notices the transition from “we know this system” to “we operate this system”.
The cost is in the options you stop pricing
This is the part that finance actually needs to hear, and it is the part that never gets said, because it does not appear in any ledger.
The value of a software system is not its current behaviour. It is its current behaviour plus the set of changes you could make to it cheaply. That option set is the whole reason you built rather than bought. When a region becomes incomprehensible, the options attached to it do not get more expensive. They get removed from consideration before anyone prices them.
Nobody writes down “we did not consider changing the pricing engine”. The idea dies in a corridor, in the half second where someone imagines the work and does not raise it.
What is different about the fix
I want to be precise, because “read more code” is not a strategy and I am not proposing it.
The intervention that works is targeted re-entry. Pick one avoided region per quarter. Send one engineer in with an explicit brief that the deliverable is understanding, not a change: a written description of what it does, what invariants it assumes, and what would break. Give it a week, treat it as delivery, and accept that a quarter of the time they will come back and say the module is fine and the fear was inherited from someone who left.
The second intervention is provenance, and this is where an agentic pipeline can genuinely beat what preceded it. When nobody remembers why a line exists, a durable chain from that line back to the change, the acceptance criteria and the approver answers the question that memory used to answer. Human processes never produced a complete record of that. A machine-mediated one can, and it is close to the only structural advantage on offer here.
The third is a generation policy. If a region is high-risk and low-comprehension, that is exactly where you should be generating least and reviewing hardest. Most teams have this backwards, because the scary region is also the one where an agent’s confident output is most welcome.
Where this breaks down
Not all code deserves comprehension. A well-bounded service with a strong contract, good tests and a low change rate can be a black box safely, and forcing a team to understand it wastes attention that belongs elsewhere. My argument, taken literally, would have you paying down debt on things that will never bill you.
The routing-around behaviour is sometimes correct. Building next to a bad subsystem rather than inside it is the strangler pattern, and it is a respected strategy. I have described it as a symptom of fear, and in a real organisation the difference between deliberate containment and cowardice is legible only in whether anyone wrote the plan down.
Turnover produced the same effect and we survived it. Codebases have always contained large amounts of code no current employee understood. Institutions muddled through for decades. The honest version of my argument is that the rate has changed, not the kind, and rate arguments are weaker than they sound because systems often have more slack than the person warning about them assumes.
My measurements are soft. Two of the four signals I listed are behavioural observations that cannot be instrumented, and the most important one is unmeasurable by construction. I am asking you to act on a cost I have admitted you cannot count, which is exactly the move I criticise vendors for making.
Provenance is not comprehension. A complete record of why a change was made does not mean anyone has a model of the system. It answers a local question well and a structural one badly, and I have leaned on it harder than that distinction supports.
The takeaway
Code debt makes change expensive, which is survivable, because expensive things still get done. Comprehension debt makes change feel unsafe, and unsafe things get silently dropped from the plan.
That is why it is worse, and why refactoring is the wrong instinct: you cannot refactor your way into having read something, and doing it with agents nobody is reviewing closely just produces more unread code on top of the unread code.
If you take one thing into next week: at your next planning session, ask which part of the system people were relieved not to have to touch. That answer is your map, and it costs nothing to collect.