MVP Rescue · Teardown

What breaks in AI-generated codebases — and how to fix it

AI app builders get a working product in front of users faster than ever. The same speed tends to leave the same gaps behind. These are the failure patterns that most often stand between an AI-built MVP and a product you can safely charge for — what you'll notice, why it happens, and how it's fixed.

Kosi Digital engineering · Published

1. No tenancy model

Symptom
Everything works with one test account. Then a second customer signs up and can see — or edit — the first customer’s records, or every query quietly returns everyone’s data.
Why it happens
Prompts describe screens, not ownership. The generated schema has users and records but no organisation or workspace, so “whose data is this?” is answered per query, if at all.
The fix
Add an explicit tenant (organisation/workspace) table, put a tenant id on every tenant-owned table, and enforce the filter in one place — database row-level security or a single data-access layer. Then add a test that proves tenant A cannot read tenant B.

2. Secrets in the client

Symptom
API keys for payments, email, AI providers or the database service role sit in the JavaScript bundle. Anyone who opens the browser’s developer tools can copy them and run up your bill or read your data.
Why it happens
The quickest way to make a third-party call work in a generated front end is to call it directly from the browser with the key inline.
The fix
Rotate every exposed key first. Move the calls behind server-side functions or an API, keep secrets in environment variables on the server, and leave only publishable keys in the client.

3. Missing authorisation checks and RLS

Symptom
The UI hides buttons from people who shouldn’t use them, but the endpoints behind them answer anyone with a session — or anyone at all. Database tables are readable with the public key because row-level security is off.
Why it happens
Generated code tends to check “is the user logged in?” on the page and stop there. Backend-as-a-service tools ship with permissive defaults during prototyping, and nobody turns them back on.
The fix
Enable row-level security (or security rules) on every table with policies per role, check permissions on the server for every action on a specific record, and add tests that call endpoints as the wrong user.

4. N+1 queries

Symptom
Dashboards and list pages are fast in the demo and slow down sharply as data grows. The database shows hundreds of near-identical queries for a single page load.
Why it happens
Generated components often fetch related data inside a loop — one query for the list, then one more per row — because that is the simplest code that renders correctly.
The fix
Load related data with joins or batched queries, paginate lists, add indexes on the columns you filter and join by (tenant id first), and turn on slow-query logging so regressions show up.

5. No migrations

Symptom
Nobody is sure what the production schema is. Changes were made by clicking in the database console, staging and production have drifted apart, and a deploy breaks because a column is missing.
Why it happens
AI builders and hosted databases make it easy to change tables in place. The schema lives in the database, not in the repository.
The fix
Capture the current production schema as a baseline migration, commit it, and make every future change a reviewed migration file applied by the deploy — never by hand.

6. No tests and no CI

Symptom
Every change is a gamble. Fixing one screen breaks another, and you find out from a customer. Regenerating a component with the AI tool silently undoes an earlier fix.
Why it happens
Prompt-driven development optimises for “it works when I click it now”. Tests and pipelines are not part of the prompt, so they never appear.
The fix
Put the code in a repository you own, add CI that runs lint, type-check and tests on every change, and start with tests for the paths that cost money or trust: sign-up, login, payments, permissions and the core workflow.

7. No observability

Symptom
Users report “it’s broken” and there is nothing to look at: no error tracking, no searchable logs, no uptime alert. Outages are discovered by customers.
Why it happens
Monitoring is invisible in a demo, so it is never requested — and the default hosting logs disappear quickly or are hard to search.
The fix
Add error tracking to the front end and back end, structured logs with a request id (and no secrets), an external uptime check on a health endpoint, and an alert that reaches a person.

Check your own app

Run through the MVP-to-production readiness checklist (40 checks), or request a free Rescue Scan and an engineer will record a 15-minute review of your live app. For the full engagement, see MVP Rescue.

Frequently asked questions

Is code generated by Lovable, Bolt, v0 or Cursor safe to run in production?
It can be, but it rarely is by default. The usual gaps are tenancy, secrets in the client, missing authorisation checks, slow queries, unmanaged schema changes, no tests and no monitoring. Each one is fixable without starting over if it is caught before real customer data piles up.
Should I rebuild or refactor an AI-generated codebase?
Refactor when the data model is roughly right and the problems are in security, performance and process. Consider a rebuild of the affected parts when the data model has no concept of tenants or ownership, because every feature sits on top of it.
What should I fix first?
Rotate and move any exposed secrets, then close authorisation and row-level security gaps, then tenancy. Those three decide whether customer data is safe. Performance, migrations, tests and monitoring come next.
How do I find out which of these my app has?
Work through the MVP-to-production readiness checklist, or request a free Rescue Scan and an engineer will record a 15-minute review of your live app.

Ready to talk about your product?

Tell us what you are building or fixing. An architect replies within 4 business hours with a clear next step, whether or not we work together.

A real person replies within 4 business hours — IST · GMT · EST overlap. Or use the contact page.