The Production Risks of Vibe Coding

Vibe coding is a real way to ship software now. It is also a specific set of failure modes when those apps meet real users. Here is where they break.

“Vibe coding” — building software by describing what you want to an AI and accepting most of what it gives you — is a legitimate way to make working software in 2026. We’re not here to be sniffy about it. Plenty of useful products started as vibe-coded prototypes, and a few of them are now revenue-generating businesses.

But vibe-coded apps fail in specific, predictable ways once real users show up. The pattern is consistent enough that you can almost write the post-mortem in advance. This post is the post-mortem written in advance, so you can avoid being its subject.

What vibe coding is good at

Before the warnings, credit where it is due. Vibe coding is genuinely good at:

  • Getting from idea to clickable thing in days, not weeks.
  • Producing UI that looks more polished than a typical hand-rolled MVP.
  • Wiring up the boring 80% — forms, lists, simple CRUD, basic auth flows.
  • Letting non-engineers test product ideas without hiring a team.

If you have a working vibe-coded app, you have already done something hard. The question is whether the way it was built will hold up under load, attackers, and time. Most of the time, the honest answer is “partially.”

Where vibe-coded apps tend to fail

These are the patterns we see again and again on real codebases. None of them are the model’s fault, exactly. They are what happens when nobody is holding the part of the picture the model can’t see.

1. Authorization is missing or wrong

Logging in works. Almost every vibe-coded app gets login working. What frequently does not work is the check that user A cannot view, edit, or delete user B’s data. The model writes if (user) { ... } and moves on. Nobody asks “is this user allowed to operate on this specific record?”

This is the single most common, most dangerous, and most invisible failure mode. It is invisible because everything looks fine when you’re the only user. It becomes visible the first time someone curious increments an ID in the URL.

2. Secrets in places they should not be

API keys committed to the repo. .env files pushed to GitHub. Stripe secret keys in client-side bundles. Database connection strings in seed scripts. Webhook URLs with no signature verification, accepting payloads from anyone on the internet who guesses the path.

These show up because at the moment the model wrote the code, hard-coding was the path of least resistance. Nobody came back later and asked “should this still be here?“

3. Data exposure through over-fetching

The page needs the user’s name. The endpoint returns the user’s entire row, including hashed password, password reset token, admin flag, internal notes, and any field a future migration adds. The browser gets all of it. Anyone who opens dev tools sees all of it.

You don’t need a hack to exploit this. You need curiosity.

4. Background jobs and webhooks that aren’t idempotent

Payment provider sends the webhook twice (this is normal, by design). Your handler processes it twice. The user gets charged twice, or the order ships twice, or the credit gets applied twice. The model wrote a function that does the thing; nobody asked what happens if the thing gets called again.

5. No backups, or backups that have never been tested

“My host backs it up” is something people say when they have not actually checked. Even when the host does back it up, restoring is a different operation, with different permissions, on a different timeline. An untested backup is a hope, not a recovery plan.

6. Production and staging that share infrastructure

The dev database is the prod database. The staging API hits real Stripe. The test account sends real emails. CORS allows any origin because that was how the model got the cross-origin call working at 11pm. None of this is necessarily broken on day one. All of it is a trap.

7. No observability

The first time you find out something is broken is when a user emails you. There are no logs you can search. There is no error tracking. The metrics are a graph of HTTP 200s, which is not the same as “the app works.” The model didn’t add monitoring because you didn’t ask for it.

8. Dependency sprawl

Vibe-coded apps tend to accumulate dependencies. Each feature pulls in whatever package the model reached for first. Some are well-maintained. Some have not seen a release in three years. Some are typo-squats nobody noticed. The total surface area is rarely audited.

9. AI-shaped architecture

The codebase has the shape of “the model wrote a thing, then wrote another thing that mostly does not interact with the first thing.” There is no domain model. There is no shared validation. The same business rule lives in three places, slightly differently, because each was generated in a different conversation.

This isn’t fatal on day one. It becomes fatal around feature seven, when fixing one bug breaks two others.

10. The bus factor is one model conversation

When something breaks at 2am, the path forward is “open a chat and try to re-explain the system to an AI that has no memory of having built it.” That is fine for moving fast. It is rough for keeping a paying customer’s data intact during an incident.

What this is not

This is not an argument against AI-generated code, or against vibe coding, or against shipping fast. The fastest path from idea to revenue still often runs through a vibe-coded MVP. The point isn’t to slow that down.

The point is that after the MVP works, there is a separate body of work — hardening, auditing, instrumentation — that AI tools are currently not very good at doing on their own, because it requires asking adversarial questions the model wasn’t prompted with.

What to do about it

Three honest options.

Audit and harden, keep the codebase. A senior engineer reads the code with a specific list of attack and failure scenarios in mind, produces a prioritized fix list, and either executes the fixes or hands them back for the founder to execute (often with the same AI tools). For most vibe-coded apps that work and have a real user base, this is the right move. Vibe Code Audit and Production Hardening are designed for this.

Audit, then maintain. When the founder isn’t an engineer and the app is already in production, the audit is just step one. Step two is ongoing support — bug fixes, deploys, dependency updates, incident response. See Maintenance for AI-Built Apps.

Rebuild the dangerous parts. Sometimes a single subsystem (auth, billing, data export) is so risky that re-implementing it is faster than fixing it. The rest of the codebase usually stays. We’ll cover when this applies in a separate post.

The honest summary

Vibe-coded apps tend to be 80% of a real product, with the missing 20% distributed across exactly the parts that matter when a user, regulator, or attacker shows up. Knowing which 20% is missing in your codebase is the work. Doing that work well is the difference between a product that grows and a product that quietly bleeds users every time something breaks.

If you’ve shipped a vibe-coded app and want a senior engineer to tell you honestly where the gaps are, get in touch.

If this is your week

Get a senior read on your codebase before launch.

A one-week audit, fixed price from $1,500. NDA before access. Written report your team can act on.

More writing