Is my Lovable app production-ready?
Your app works. People can sign up, click through it and do the thing it was built to do. That is a real achievement and it is not the same question as whether it is ready for strangers. Here are the twelve checks that actually decide it, in the order we run them.
“Production-ready” is a vague phrase that usually means something specific: the app can take real users, hold real data and process real money without a preventable incident. A prototype can be excellent and still fail every one of those tests, because nothing in the prompt asked for them.
None of this is a criticism of the tool. Generation models optimise for a screen that renders and a flow that works. Almost every production control is invisible on screen — nobody notices correct authorization, they only notice its absence. So it does not get built unless someone asks for it by name.
Work through these twelve. You can do most of them yourself in an afternoon with a browser.
Secrets and keys
1. Are any keys in the front-end?
Open your live app, view the page source, and search the JavaScript for sk_, service_role, AKIA and api_key. Anything a browser downloads is public, permanently, to everyone. A publishable Stripe key or a Supabase anon key belongs there by design. A secret key, a service-role key or an admin token does not.
If you find one, rotating it is the first move, not the last. Assume anything that was ever public has been read.
2. Is there a .env in the repo?
If your repo is public, check whether the environment file was committed at some point — including in history, where deleting the file does not remove it. This is one of the most common ways a small project ends up with a compromised database.
Who is allowed to do what
3. Is sign-in decided by the server or by the browser?
The test: sign in, open your browser’s developer tools, look for a stored value like isLoggedIn or user or role, and change it. If the app now believes you are someone else — or an admin — the decision is being made in a place the user controls.
Anything the browser can edit is not a security control. It is a convenience.
4. Can you reach a protected page by typing its address?
Sign out, then paste the URL of a page that should require an account. If it loads, even briefly, before redirecting, the page is being protected by the interface rather than by the server.
5. Can one user read another user’s data?
This is the one that causes real damage. Create two accounts, put something in each, and then try to fetch the second account’s records while signed in as the first — usually by changing an ID in a URL or an API call. If it comes back, your data is shared and it will not stay quiet forever.
With Supabase specifically, check whether row-level security is enabled on every table and whether there are policies that actually restrict rows. An enabled RLS with a permissive “allow all” policy is the same as no RLS, and it is a common outcome when the prompt was “make it work”.
Data
6. Is the data actually stored anywhere?
Reload the page. Then open it on a different device. If your data is gone, it never left the browser. Plenty of prototypes look complete and hold everything in memory, which is fine until it is not.
7. Are there backups, and has a restore ever been tested?
A backup that has never been restored is a hypothesis. Find out what your database provider takes automatically, how far back it goes and what the restore procedure is — before you need it at 2am.
8. What happens when something fails?
Turn off your network mid-action and watch. A production app tells the user what happened and leaves the data consistent. A prototype often shows a spinner forever, or reports success for something that never saved.
Money
9. Is payment confirmed by your server or by the success page?
If access is granted when the browser lands on /success, then anyone who visits that address gets access. Payment has to be confirmed by a verified webhook from the payment provider, checked with the signing secret, and recorded server-side against the account.
10. What happens on a failed, disputed or cancelled payment?
Subscriptions end, cards expire, people charge back. If your app has no path for removing access, you will be handling those by hand forever.
Where it runs
11. Is there any separation between testing and live?
If you are editing the thing your customers are using, every change is a live experiment. A separate environment — with its own database and its own keys — is the single change that most reduces the chance of a self-inflicted outage.
12. Would you know if it broke?
If your app went down or started throwing errors right now, how would you find out? For most prototypes the honest answer is “a user emails me”. Uptime and error monitoring are cheap, often free at small volumes, and they change how you sleep.
What the answers add up to
If you got clean answers to 1–5 and 9, you are in better shape than most AI-built apps that reach us. If you did not, that is completely normal and it is fixable — usually in days rather than months, and usually without touching the product you already built.
What it is not is a reason to rewrite. The prototype is proof that people want the thing. Throwing it away throws that away too.
Common questions
Does this apply to Bolt, v0, Replit and Cursor too?
Yes. The tools differ in output but the gaps are the same, because they come from the same cause: production controls are invisible on screen, so nothing in a prompt asks for them.
I found something serious. What do I do first?
Rotate any key that was ever public, then close whatever lets one account read another account’s data. Those two are the ones that turn into an incident you have to disclose. Everything else can be sequenced.
Can I just ask the AI tool to fix these?
Sometimes, for narrow items. The difficulty is that verifying the fix takes the same expertise as making it — a model will happily tell you authorization is now enforced. If you cannot check the claim, you have not really closed the issue.
Find out where your own app stands
The free production-readiness scan checks your live app for these problems and comes back with a score, a prioritized list and an estimated remediation range. No call, no commitment.