How to Fix AI-Generated Code and Make a Vibe-Coded App Production-Ready
How to fix AI-generated code before real users arrive: the failure patterns in vibe-coded apps, a triage order, a production checklist, and when to rebuild.
To fix AI-generated code, stop adding features, get a senior engineer to audit what you have, and fix it in order of what can hurt you: security first, then data, then payments, then reliability, then maintainability. Most vibe-coded apps do not need a rewrite. They need the review that never happened: secrets moved to the server, authorisation on every endpoint, validation on the server, verified payment webhooks, real migrations, tests on the critical paths, and monitoring. After that, you can keep using AI tools, just with guardrails.
The pattern is now familiar. A founder builds a working product with Cursor, Lovable, Bolt or Claude, gets the first users, and then something breaks in a way the tools cannot explain. Sometimes it is a bug. Sometimes it is a stranger reading every customer’s data. This article is how we approach making a vibe-coded app production-ready, and what you can check yourself before you call anyone.
What AI coding tools get right
Credit first, because it is deserved. AI coding tools are genuinely good at:
- Scaffolding a project with a sensible framework and folder structure.
- Producing working UI quickly, often better looking than a developer’s first draft.
- Writing standard CRUD logic and forms.
- Getting a demo in front of users in days instead of months.
That last point matters. A vibe-coded prototype that proved people want the product is not a mistake. It is a cheap answer to the most expensive question in a startup. The problem starts when the prototype becomes the production system without anyone deciding that it should.
Why vibe-coded apps break in production
AI tools optimise for “it works when I click through it.” Production needs “it keeps working when a thousand people click through it, some of them hostile, some of them with bad data, at the same time.” The gap between those two is where the bugs live.
Three structural reasons:
- The happy path is all the model sees. It builds what you described. You described what should happen, not every way it could go wrong.
- Context runs out. In a larger codebase the model does not see every file, so it re-implements logic it already wrote elsewhere, slightly differently each time.
- Nobody reviews the diff. When the tool writes hundreds of lines per prompt and the app still runs, the natural thing is to accept and move on. That is how a missing permission check survives.
The failure patterns we find most often
| Symptom | Usual cause | Fix |
|---|---|---|
| API keys visible in the browser’s network tab or JS bundle | Secret keys used from frontend code | Move calls to a server route, rotate every exposed key |
| Any logged-in user can read other users’ data | Database rules disabled or too broad (for example, row-level security off in Supabase), no ownership checks in API routes | Enforce authorisation on every query and endpoint, test it with two accounts |
| Bad data in the database, odd crashes | Validation only in the form, none on the server | Validate every input on the server with a schema |
| Duplicate charges or paid users without access | Stripe webhooks not verified, not idempotent, or missing | Verify signatures, store event IDs, make handlers safe to run twice |
| Database changes break production | Schema edited by hand or by the model, no migrations | Introduce migrations and a repeatable schema history |
| Pages slow down as data grows | No indexes, queries inside loops, fetching whole tables | Add indexes, batch queries, paginate |
| Fixing one bug creates two more | The same logic duplicated across files | Consolidate into shared modules, add tests before refactoring |
| You find out about errors from users | No error tracking or structured logs | Add an error tracker and logging on the server |
| Deployment only works from one laptop | Manual deploys, environment set up by hand | A CI pipeline that builds, tests and deploys from the repository |
| Unknown packages in the dependency list | Hallucinated or unnecessary packages | Remove what is unused, verify every package is real and maintained |
The dependency row deserves a sentence of its own. Models sometimes suggest packages that do not exist, and attackers have started registering those names with malicious code inside, a practice now called slopsquatting. If your project was built by accepting install commands without reading them, check every dependency.
A quick self-check before you call anyone
You can run these checks yourself in under an hour, without being an engineer:
- Open your app, open the browser developer tools, and look at the network tab. Do any requests carry keys that look like secret API keys (OpenAI, Stripe secret keys, database service keys)? If yes, those keys are public.
- Create two test accounts. Log in as the first, find a URL or API request that loads your own data, and change the ID to one belonging to the second account. If you can see it, so can anyone.
- Search your repository for “sk_”, “secret”, “password” and “key”. Anything that looks like a real credential in the code is a problem.
- Pay for something twice in Stripe test mode, and refund once. Does your app’s state match Stripe’s?
- Ask: if the database disappeared tonight, how would we restore it? If nobody knows, that is your first fix.
- Ask: how would we know if sign-up broke at 3am? If the answer is “a customer would email us”, you need error tracking.
If any of these fail, do not panic, but do stop adding features until they are fixed.
The triage order for fixing AI-generated code
Do not fix things in the order you find them. Fix them in the order they can hurt you.
1. Security. Exposed secrets, missing authorisation, open database rules, unprotected admin routes. These can turn into a data breach overnight, with legal consequences under GDPR and similar laws. Rotate keys, lock down access, verify with tests.
2. Data integrity. Server-side validation, migrations, backups you have actually restored, and constraints in the database. Bad data is easy to create and very expensive to clean up later.
3. Payments. Verified, idempotent webhooks, a reconciliation check against Stripe, and correct handling of failed payments, refunds and cancelled subscriptions. Money bugs cost trust faster than any other kind.
4. Reliability. Error tracking, logging, health checks, a deployment pipeline, and performance basics like indexes and pagination.
5. Maintainability. Remove duplication, set up types and linting, add tests to critical paths, and document how the system fits together. This is what lets you keep shipping without fear.
Features come after. That feels slow, but every feature built on an unchecked base adds to the eventual cost of fixing it.
Fix, refactor or rebuild?
| What the audit finds | Verdict |
|---|---|
| Sensible structure and data model, security and payment gaps | Fix in place, add tests and CI |
| Works, but logic duplicated everywhere and changes keep breaking things | Refactor in stages, behind tests |
| Data model fundamentally wrong for the product | Rebuild the core, migrate data |
| Stack chosen by the tool cannot meet your security, compliance or scale needs | Planned migration, keeping what works |
| Small prototype, few users, mostly UI | A clean rebuild may be cheapest, reusing the UI |
Most vibe-coded apps land in the first two rows. Be careful with anyone who recommends a full rebuild without reading the code, because it is the most expensive option and rarely the necessary one. The same logic applies to any inherited codebase, and our guide on how to take over a software project covers the access and handover side if a freelancer or agency built part of it.
Production-readiness checklist for an AI-built app
Before you send real users or real money through it:
- No secret keys in frontend code, and every previously exposed key rotated.
- Authorisation checked on every API route and database query, tested with two accounts.
- Server-side validation on every input.
- Database migrations in the repository, and automatic backups with a tested restore.
- Payment webhooks verified, idempotent and reconciled.
- Error tracking and server logs in place.
- A CI pipeline that type-checks, lints, tests and deploys.
- Tests on the critical paths: sign-up, login, payment, and the core workflow.
- Dependencies reviewed, unused ones removed, all of them real and maintained.
- Rate limiting on login, sign-up and any endpoint that calls a paid AI API.
- Privacy policy, cookie consent and data handling that match what the app actually does.
- Someone, not something, can explain how the system works.
The rate limiting point is easy to miss in AI products. An endpoint that calls a model API without limits is an invitation for someone to run up your bill.
Keep using AI tools, with guardrails
The answer is not to stop using AI tools. We use them every day. The answer is to put them inside a process that catches what they miss:
- Types and linting catch a class of mistakes before the code runs. TypeScript in strict mode is a cheap safety net for AI-written code, and it is one reason our TypeScript developers insist on it.
- Tests on critical paths let you accept AI-written changes without fear of silently breaking payments.
- CI that blocks broken builds means nothing reaches production without passing the checks.
- Human review of every diff before it merges. Not every line in detail, but every change, with special attention to auth, data access and money.
- Small prompts, small changes. Asking for one function at a time produces reviewable code. Asking for a whole feature produces a wall of code nobody reads.
If your product has AI at its core, such as model calls, retrieval or agents, those parts need their own evaluation and guardrails. Our AI development service covers that side.
What it costs to fix a vibe-coded app
The honest answer is that it depends on size and state, which is why we audit before quoting. A small app with a sound structure might need a focused pass. A larger app with tangled logic and real users needs more care. As a reference point, rebuilding the same product from scratch with a professional team falls in the market ranges in our custom software development cost guide, and a well-scoped fix is usually a fraction of that.
The thing to avoid is an open-ended clean-up billed by the hour with no defined finish line. Get the audit, agree a written list of fixes, and get a fixed price for that list.
How we handle these projects
This is a large part of our software rescue work. It starts with an audit, a written verdict on what is healthy and what is risky, and a recommendation to keep, refactor or rebuild. If you want us to do the fix, you get a fixed price for the agreed list. If our estimate is wrong, the extra hours are our cost. Changes you ask for along the way are quoted separately before work starts. You keep the code, the repository and everything we write.
If you are still at the idea stage and deciding what to build properly this time, our MVP scope checklist is the place to start.
The short version
- AI-generated code fails on what nobody asked for: auth, validation, secrets, errors.
- Run the six self-checks before anything else.
- Fix in order: security, data, payments, reliability, maintainability.
- Most vibe-coded apps need fixing, not rebuilding.
- Keep using AI tools, behind types, tests, CI and review.
If your app was built with AI tools and you are not sure what is underneath, start with a free code audit. A senior engineer reads the code and tells you in writing what is safe, what is risky, and what to fix first, with a fixed quote for the fix if you want one.
FAQ
Is AI-generated code safe to use in production?
It can be, once someone has reviewed it the way they would review any other code. The problem is not that a model wrote it, but that nobody checked it. AI tools reliably produce code that works on the happy path and regularly skip authorisation, input validation, secret handling and error cases. Review, tests and a security pass make it production-ready.
What are the most common problems in vibe-coded apps?
API keys exposed in the frontend, database access rules that let any user read any row, missing server-side validation, payment webhooks that are not verified or idempotent, no database migrations, no tests, duplicated logic across files, and no error tracking. Most of these are invisible in a demo and appear only when real users, or attackers, arrive.
Should I rebuild my AI-generated app from scratch?
Usually not. If the data model is sensible and the app works, fixing and hardening it is faster and cheaper. Rebuild when the data model is wrong for the product, when the code is so duplicated that every change breaks something else, or when the stack itself cannot meet your security or scaling needs. An audit should give you that call with reasons.
How long does it take to make a vibe-coded app production-ready?
It depends on size and state. A small app with sound structure might need a focused pass on security, payments, data and deployment. A larger app with tangled logic needs more. Get an audit first, then a fixed quote for a defined list of fixes, so the clean-up does not become open-ended.
Can I keep using Cursor, Lovable or Bolt after the app is fixed?
Yes. The fix is not to ban AI tools but to put guardrails around them, such as type checking, linting, tests on critical paths, a CI pipeline that blocks broken builds, and human review of every change before it reaches production. With those in place, AI tools become a faster way to write code that still gets checked.
What is slopsquatting and why does it matter for AI-generated code?
Slopsquatting is when attackers publish malicious packages under names that AI models tend to hallucinate. If a model suggests installing a package that does not exist and someone has since registered that name, installing it can run malicious code. Every dependency in an AI-generated project should be checked against what you actually need and verified as a real, maintained package.