Guides
The technical debt of vibecoding
Vibecoding does not create a different kind of debt from the classic sort. It creates it far faster, and without the signals that usually raise the alarm.
Updated 21 August 2026 · 5 min read
A vibecoded project rarely goes badly in its first month. It works, it looks good, it cost a third of the estimate. Trouble starts around month six, when something needs changing and nobody knows where or how.
That lag explains why the subject is handled poorly: at the moment you decide to adopt vibecoding none of the costs are visible yet, and by the time they are, the decision is old.
A different kind of debt
Classic technical debt results from conscious trade-offs. You know you cut a corner, you know where, someone left a comment or opened a ticket. It is documented by the very fact of having been chosen.
Vibecoding debt was not chosen. Nobody decided that this module would duplicate the logic of the one next to it; it happened because both were generated separately, two weeks apart, without the model knowing the first existed. So there is no trace, no awareness, no ticket.
The four shapes it takes
Code nobody understands
The most direct form. The code works, it is even well written, but no human on the project holds a mental model of how it operates. As long as nothing breaks, that does not matter. The day a specific behaviour needs fixing, you find yourself doing archaeology on code a machine wrote three months ago.
The test is simple and brutal: pick a file at random and try explaining out loud what it does and why it does it that way. If you cannot manage it for more than a third of your files, the debt is already in place.
Accidental architecture
Each request produces a locally reasonable answer. Added together, those answers form a structure nobody designed. You end up with three different ways of reaching the data, two naming conventions, and business logic scattered between client and server depending on the order the screens were generated in.
This is not bad architecture, it is architecture by sedimentation. It makes every change unpredictable: you cannot tell whether altering one thing will break another, because no rule states what depends on what.
Invisible duplication
The model does not remember having already written a date formatting function. It writes another, slightly different, in every file that needs one. They all work. The day the format must change, you have to find them all — and nothing tells you how many there are.
This duplication is more dangerous than the classic kind, because the copies are not identical. A text search will not find them all.
No safety net
Without an explicit request, there are no tests. Combined with the three previous forms, that absence produces the situation that genuinely stalls a project: code nobody understands, whose structure is unpredictable, and which cannot be changed without risking a break you have no way of detecting.
The point where regenerating beats repairing
There is a reversal peculiar to vibecoding, with no equivalent in conventional development: past a certain point, throwing a module away and re-requesting it from a clean description costs less than understanding the existing one to fix it.
That is both good news and a trap. Good news because it offers an exit classic debt does not. A trap because regenerating also erases the accumulated corrections — the edge cases handled one by one after user feedback, which nobody documented.
Limiting the damage without slowing down
The goal is not to apply the full rigour of conventional development to vibecoding — that would give up what makes it useful. It is to place a few constraints where they pay off most.
- Set conventions before generating: where data lives, how things are named, what belongs server-side. Five lines suffice, and they prevent architecture by sedimentation.
- Give the model the context of what already exists rather than an isolated request. Invisible duplication almost always comes from a request framed out of context.
- Test the boundaries, not the interior. Unit tests on generated code have little value; tests verifying that a full journey works have a great deal.
- Enforce the explainable-file rule: nothing ships if nobody can say what it does. It is the most effective constraint, because it forces review without imposing rigour everywhere.
- Date and isolate prototypes. A separate folder and a note reading "generated on X, not reviewed" stops a prototype becoming a product by accident.
None of these rules slows generation down. They act on what surrounds it — the framing before, the review after — which is precisely where vibecoding saves you no time anyway.
Related reading
Spotting code written by an AI
No single signal is proof. But some patterns recur often enough to steer a review — and others, widely shared, are worthless.
Vibecode your tools instead of buying them
The maths changed. A tool that used to cost three weeks now costs two hours — but not every subscription is worth replacing.