Your Lovable app works. The screens are real, the data is real, and the demo runs clean for anyone you send it to. That’s a hard thing you already did, whatever the skeptics say. Whether the app is production ready is a separate question, and the honest answer is: not by default, and not because a scan came back green. Lovable’s own security documentation says its tools “cannot guarantee complete security” and that you are “responsible for ensuring that your app meets the security requirements appropriate for its use case.” Read that as a precise job description rather than legal hedging: the platform checks what it can see, and the rest is yours.

This post is about the rest, the specific failure layer that audits of real vibe-coded apps keep surfacing: protections that exist and don’t hold.

Is Lovable production ready by default?

No, and that isn’t a knock on Lovable specifically. No AI builder ships production readiness, because it’s a property of the one app the tool generated for you rather than a feature a platform can include: whether a stranger can read another customer’s rows, whether the server confirms payments before granting access, whether an error anywhere shows up somewhere you’ll see it, whether your data comes back after a bad delete. Each of those is checkable. None of them is visible in a demo.

The standard advice, on every forum where this gets asked, is some version of “run Lovable’s security review, fix the warnings, launch.” Do that; it catches real problems. But notice what kind of pass it is: a presence pass. It confirms protections exist, and existence is precisely the layer where Lovable apps have already failed in public.

Why the working demo proves less than you think

A demo exercises the visible fraction of an app: the screens, the happy path, the flow you designed it around. Production failures live almost entirely outside that fraction: in the request you never make, the second account you never create, the error your own clicking never triggers. From the demo side, the app that survives real users and the app that doesn’t look identical. That’s the core argument of whether an AI-built app is actually ready to launch, and it’s why “the demo went great” settles so little.

With Lovable there’s an extra twist: you may never have seen the code at all. The app was built, edited, and published inside the platform, which makes the demo the only evidence of readiness you’ve personally inspected. Everything below the interface is exactly as verified as the generator left it.

The checklist trap: protections that exist but don’t hold

Here’s the mechanism that makes checkbox-style readiness advice dangerous. AI builders are good at generating protection artifacts (RLS policies, auth middleware, rate limiters) because artifacts are what a prompt can ask for. Wiring each artifact to the thing it protects is a separate step, and skipping it produces no error: an unenforced protection behaves identically to an enforced one until someone pushes on it. Automated checks then confirm the artifact exists (enabled, present, attached), because existence is what a static check can see.

This failure class has a public name. CVE-2025-48757, the row-level-security vulnerability disclosed against Lovable-generated apps in May 2025, worked exactly this way: the researcher’s disclosure notes that Lovable’s publish check “will help ensure that RLS policies are enabled in all tables and notify if they aren’t” while it “doesn’t necessarily indicate if they are sufficient.” The check confirmed the policies were enabled; nothing confirmed they were sufficient. His follow-up scan found 303 endpoints across 170 Lovable-built projects with insufficient RLS, leaking names, emails, payment status, and API keys to anyone who queried the database with the public key those apps ship by design.

None of those founders was careless. They ran the check they were given, and the check answered a narrower question than the one they thought they were asking.

Looks fine
Actually fine
RLS is enabled on every table and the publish check passes
Every policy checks who owns the row (auth.uid() = user_id), not just that someone is logged in
The security review reports no critical warnings
A second, independent account tried to read the first account’s rows through the API and got nothing back
Rate-limiting code is in the project
The limiter is attached to the endpoint that costs you money, and a scripted loop actually gets throttled
Error boundaries exist in the code
They’re mounted on the routes users hit, and what they catch lands in a tracker somebody reads
Looks fine
RLS is enabled on every table and the publish check passes
The security review reports no critical warnings
Rate-limiting code is in the project
Error boundaries exist in the code
Actually fine
RLS is enabled on every table and the publish check passes
Every policy checks who owns the row (auth.uid() = user_id), not just that someone is logged in
The security review reports no critical warnings
A second, independent account tried to read the first account’s rows through the API and got nothing back
Rate-limiting code is in the project
The limiter is attached to the endpoint that costs you money, and a scripted loop actually gets throttled
Error boundaries exist in the code
They’re mounted on the routes users hit, and what they catch lands in a tracker somebody reads

A passing check proves your protections exist. Whether they hold is a separate test.

Why do the tools generate the artifact without the wiring in the first place? That’s a trust-boundary story, and why AI coding tools ship security holes by default explains it from the generator’s side.

What audits of real vibe-coded apps actually find

Numbers first, with their honest edges. The 26 real vibe-coded apps AxonBuild audited in June and July 2026 are the source; the stats below come from the 21 built by third parties. The corpus spans several AI builders, so none of this is a “percentage of Lovable apps”: read the figures as mechanism rates in AI-generated apps, with Lovable’s public record above showing the same mechanisms in the wild. Every finding was adversarially verified against the code, pinned to a file and line, not pattern-matched.

  1. RLS gaps in 9 of 21 apps, with cross-user access confirmed in 7. A logged-in user could read or write another customer’s data: private AI chats in one app, any user’s session in any workspace in another. The recurring shape: the policy checks that a user is signed in, and nothing checks that the row is theirs.

  2. Controls built but wired into nothing. Rate-limit buckets never attached to a route, error boundaries never mounted, a safety rulebook no running code reads. Each one passes any check that greps for its existence.

  3. A denial-of-wallet path in 12 of the 14 apps with an AI feature. A stranger or a free account could run up the owner’s paid model bill without limit. If your Lovable app calls an LLM, this is the first thing to verify.

  4. Errors recorded nowhere in 17 of 21 apps. When a user hits a bug, nothing logs it and nobody is told. This is the finding that keeps the others alive: a protection that silently failed months ago still looks fine today.

All four stop at the same halfway point: the visible half exists, and the enforcement half was never proven. A real readiness check has to test that second half, and the question it asks is whether the protection holds when pushed from outside.

Lovable and Supabase: RLS that exists vs. RLS that holds

A Lovable app with real data almost always means Supabase underneath, so the sharpest version of the presence trap is worth seeing in SQL. Both snippets are failure shapes I’ve confirmed in audited apps, rewritten in generic Supabase syntax; neither is any real app’s code.

The first is a policy that satisfies every checkbox and still leaks:

-- RLS is on, a policy exists, the publish check is satisfied.
alter table invoices enable row level security;

create policy "Users can view invoices"
  on invoices for select
  using (auth.uid() is not null);

auth.uid() is not null answers “is somebody logged in?”, so every authenticated user can read every customer’s invoices. The policy the table needed was using (auth.uid() = user_id): ownership rather than mere login. A static check sees a policy in both cases; only a request from a second account tells them apart.

The second shape is worse, because no RLS linter can see it from the policies at all:

-- A helper generated to "fix" a permissions error during a debug loop:
create or replace function get_user_invoices(p_user_id uuid)
returns setof invoices
language sql
security definer
as $$
  select * from invoices where user_id = p_user_id;
$$;

security definer means the function runs with the privileges of the role that created it, not the caller. Supabase’s own docs note that a function created by a high-privilege role like postgres “will have bypassrls privileges.” Every policy on invoices, including a perfectly correct one, is out of the picture, and the function trusts whatever p_user_id the caller supplies. In Supabase, functions like this are reachable as auto-generated RPC endpoints, so any user who can call it can request any customer’s invoices by ID. Your RLS can be flawless and this one helper walks around it.

I’ve confirmed exactly this shape in the wild. In one AI coding workspace I audited, the row-level security itself was close to flawless, so I listed the database’s helper functions before signing off. Seven were security definer, and several took a user id as a plain argument without ever comparing it to the caller’s identity: any free signup could read another customer’s private AI chats or soft-delete their projects. The good RLS was simply routed around.

The shape tends to arrive the way the comment above suggests: an AI “fixing” a permissions error by generating code that bypasses the permission system. To Lovable’s credit, its docs say the deeper scan now looks for “database functions that bypass row-level security.” The same page still ends where this post started: the tools “cannot guarantee complete security.” A pattern scanner can hunt known shapes. It can’t tell you whether your function, against your tables, hands out someone else’s rows. Only calling it can.

How to verify readiness, not just check it

Verification means pushing on the app from outside, the way a curious stranger would, and watching what happens. That’s the pass that makes your Lovable app production ready, and most of it fits in an afternoon:

  • Create two accounts. As the second, try to read and write the first account’s data by swapping IDs in API calls, not just page URLs. Reads that return rows and writes that succeed are both leaks.

  • List every security definer function in your database, and ask of each one: whose rows can this reach if a caller lies about the arguments?

  • Log out and call your most expensive endpoint (an AI call, an email send) from a terminal. Then call it fifty times in a loop from a free account. It should refuse the first and throttle the second.

  • Break something on purpose and watch where the error goes. If the answer is nowhere, a failed protection in production will be invisible too.

  • Confirm access to paid features unlocks from a server-verified payment event, never from what the browser claims about itself.

None of this requires reading the codebase, which is the point: you’re testing behavior, and behavior is the layer presence checks can’t reach. That gap, between a check that passes and a protection that holds, is the real distance from Lovable to production ready.

For the same pass across every readiness area, including the deploy, backup, and staging half covered in one database, no staging, a deploy set to break, the scorecard covers all twelve areas in about two minutes and names your weakest one first.

Common questions

Is Lovable production ready?

No, not by default, and that isn’t a knock on Lovable specifically. Production readiness is a property of the specific app it generated for you: whether row-level security checks ownership rather than mere login, whether an expensive endpoint is rate-limited, whether an error gets logged somewhere you’ll see it. Lovable’s own security review confirms those protections exist; across the 21 third-party apps in this post’s corpus, the same class of checks had gaps in 9, and in 7 of those a logged-in account could read another customer’s data.

Is Lovable safe to use?

Yes, as a tool choice: it’s a mainstream platform, and building with it wasn’t a mistake. The risk lives in what ships, in whether the specific app it built for you holds up when a stranger pushes on it.

When to bring in a pro, and the verdict to demand

If real money or customer data is on the line and you can’t run these checks yourself (or you ran them and something failed in a way you can’t interpret), outside help earns its cost. But be careful what you buy. Open-ended “hardening” quotes carry a structural bias: the more that seems wrong with your app, the bigger the engagement, so “rebuild it properly” is a conclusion that pays whoever reaches it.

Demand a verdict with evidence instead: what specifically holds, what specifically doesn’t, and whether this app should be completed or rebuilt, from someone who makes money either way and doesn’t need it to be a rewrite. That’s the deliverable the Beyond the Demo Audit is built around: an audit that ends in a rebuild-vs-complete verdict, every finding tied to the file and line that proves it. The failure classes in this post are boring, decade-old, and finite, which is exactly why completing an app is so often on the table. But it’s a call to make on evidence, in either direction; a feeling can talk you into a needless rebuild just as easily as it can talk you out of a needed one.

The same test closes this post: whether the protections hold when a stranger pushes on them. Nothing about your demo answers that. An afternoon of pushing does.