Guide · AI-built apps
If Lovable or Bolt built your app on Supabase, this is what keeps your data private, and how to check it yourself in about half an hour.
Supabase is a good choice, and it's what most AI app builders reach for when your app needs a database and logins. It's secure when it's set up properly. The trouble is that "set up properly" depends on a handful of settings the AI may or may not have got right, and you can't tell by using the app.
This guide explains the five things that matter, in plain English, and how to check each one in your own dashboard. Everything here is from Supabase's own documentation, linked as we go, because these tools change quickly.
In a traditional app, the browser talks to a server you control, and the server decides what each person is allowed to see. In most Supabase apps built by AI tools, the browser talks to the database itself, using a key that's built into the page.
That's by design, and it's fine, as long as the database knows who's asking and what they're allowed to touch. That job belongs to Row Level Security. If it isn't doing the job, the public key in your page is effectively a key to the whole table.
Row Level Security (RLS) is a set of rules attached to each table that decide which rows a given user can read, add, change or delete. Supabase describes each policy as working like an extra condition added to every query on that table.
The important bit: Supabase's docs say a table in an exposed schema without RLS is readable and writable by any role with a grant on it. On most projects that includes visitors who aren't logged in. So a customers table with RLS off can be read by anyone who has your app's public key, which is anyone who has loaded your app.
Once RLS is on, the reverse is true: nothing is reachable with the public key until you add policies that allow it.
This is the one AI tools get wrong most often, because an over-generous policy makes an error go away and the app starts working.
A policy with using (true) means "every row, for everyone this policy applies to". Supabase's docs say to use that only for data that is meant to be public, such as a list of products. On a table of orders, messages or profiles it means every user can read every other user's records.
Two other patterns to watch for:
Supabase has two kinds of key, and it renamed them recently, so tutorials and AI tools use both sets of names:
sb_publishable_), which replaces the old anon key. Supabase says it's safe to expose online, in your web page or app. It only gets what your RLS policies allow.sb_secret_), which replaces the old service_role key. Supabase is blunt: it "bypasses every Row Level Security policy you have". It must only ever be used on a server you control.The old keys are long strings starting eyJ. They still work alongside the new ones, and Supabase says they're being deprecated by the end of 2026, so it's worth moving over and then switching the old ones off in Settings, API Keys.
service_role and sb_secret_.Uploaded files live in Storage buckets, and access to them is controlled by policies on the storage tables, in the same way as your other data. A bucket marked public is readable by anyone with the link, which is fine for product photos and not fine for passports, contracts or invoices.
Under Authentication settings, check:
Database functions normally run with the permissions of whoever calls them. A function marked security definer runs with the permissions of whoever created it, which on Supabase is usually an account that bypasses RLS. Supabase's docs say such a function can return rows the caller isn't allowed to read, and by default anyone can call it, including people who aren't logged in.
AI tools write these to get round an RLS error. Sometimes that's the right fix; often it quietly undoes your security. The Security Advisor warns when a security definer function can be run by signed-out or signed-in users, and when a function's search path isn't fixed.
Not strictly security, but it's what saves you if something goes wrong. Supabase's free plan doesn't include daily backups; Pro keeps 7 days, Team 14 and Enterprise up to 30, and point-in-time recovery is a paid add-on. If you're on the free plan with real customer data, export it regularly and keep a copy somewhere else. Whatever plan you're on, try restoring one before you need to. Our guide on testing your backups covers how.
If you would rather someone else went through all this, there are three routes, and they suit different jobs.
Supabase's own experts list. Supabase keeps a directory of agencies and developers with specialist experience on the platform, at supabase.com/partners/experts. If you are building something new and want a Supabase agency that lives in the platform, start there.
Freelance marketplaces. Upwork, Fiverr and Contra all let you hire Supabase developers by the hour. Fine for a well-defined task; check their past work, and keep the project and its keys in your own account.
An independent review. That is us. We are not an official Supabase partner and we would not call ourselves a Supabase consultant in that sense. We are developers who build with AI every day, and most of the Supabase projects we see were set up by Lovable, Bolt or a similar tool. We read every table's policies, the functions, the storage rules and the code that calls them, then fix what is wrong or tell you exactly what to fix. The code, the project and the keys stay yours throughout. Our guide to hiring a developer to finish your AI app has the questions to ask whoever you choose.
Open the Security Advisor in your Supabase dashboard and deal with anything marked as an error first, especially "RLS disabled in public". Then read each table's policies, check which storage buckets are public, check your login settings, and make sure the secret (service_role) key never appears in front-end code.
Rules attached to each table that decide which rows each user can read, add, change or delete. Because most Supabase apps talk to the database straight from the browser using a public key, RLS is what stops one user reading another's data, or a stranger reading all of it.
Yes, the anon key (now called the publishable key) is designed to be public, but only because Row Level Security limits what it can do. If a table has RLS off or a policy that allows everyone, the public key can reach that data. The service_role key (now the secret key) is never safe to expose.
It runs automatic checks on your project and flags issues such as tables with RLS disabled, policies that exist but aren't enforced, policies that allow unrestricted access, views and functions that bypass RLS, and public storage buckets that can be listed. It's a good first pass, but it can't tell whether your policies match your business rules.
In our experience: tables with RLS switched off, policies that let every user see every row, the secret key used in front-end code, security definer functions written to get round an error, public storage buckets holding private files, and open sign-up on apps that should be invite-only.
Plenty of warnings are fine for your situation. A few really aren't. We'll tell you which is which.
What we will cover:
Rather talk now? Book a call or ring 01474 639 089.
We reply within one working day.