Teardown · 5 min

What breaks first in a vibe-coded app

Vibe coding works. It just doesn't make the boring decisions. Here's the order things break, based on what has actually gone wrong in public.

Vibe coding works. You describe what you want, the tool builds it, and something real exists by the end of the afternoon. That is not a trick — it is a genuine shift in what one person can produce.

What it does not do is make the boring decisions. Those are still yours, and if nobody makes them the application ships without them. Here is the order things tend to break, based on what has actually gone wrong in public.

1. The database is readable by anyone

The most common failure by a distance. Modern app platforms expose your database directly to the browser and rely on row-level security rules to decide who sees what. Generate an app without writing those rules and the default is often wide open — every row, to anyone who knows the endpoint.

This is what turned one platform's flaw into an estate-wide problem: not one broken app, but the same missing rule replicated across 170+ applications built the same way.

Check it in five minutes: open your app, find the API endpoint in the network tab, and call it with no authentication. If you get data back, so can everyone else.

2. Keys are in the browser

A generated app frequently puts API keys where the code that uses them lives — which, for anything client-side, means shipped to the user. Service keys, admin tokens and third-party credentials all end up viewable in the bundle.

The tell is a variable name with "secret" or "service" in it inside anything the browser downloads. Anything that grants write access belongs on a server you control, never in the client.

3. Nothing limits how fast the endpoint can be called

Generated backends rarely include rate limiting, because nobody asked for it. That is fine until an endpoint calls a paid model. Then someone loops it, and you find out what your monthly bill can look like.

4. Uploads are trusted

File uploads that accept anything, store it under a predictable path and serve it back are a well-worn route to compromise. The controls — type validation, size caps, a storage bucket that never executes what it holds — are unglamorous and almost never generated by default.

5. There is no record of what happened

When something does go wrong, the first question is what the system touched and when. Generated applications log almost nothing useful, so the honest answer is that nobody knows. That converts a contained incident into an open-ended one.

None of this is an argument against building fast

Building fast was right. The tools are good and the speed is real. The mistake is assuming the output is finished because it runs — the missing parts are invisible in a demo by construction, because a demo only exercises the path you chose to show.

Work down the five above in order. If you would rather have someone else do it properly, that is what the Reality Check is for: one week, fixed price, and a written list of what would break first.

This is the part we do — the crossing from a demo to a system that survives production.