Is my app safe to launch?
You built something that works. Now you want to put it in front of people, and nobody has told you whether that's a reasonable thing to do.
This is the list we run through when someone asks us that question. None of it needs you to be a security engineer, and each check is written so you can do it yourself in an afternoon. The first three are the ones that turn into real incidents — if you get through those clean, you're past the dangerous part.
Can anyone read your API keys?
Everything your app ships to the browser is public — the code, the config, and every string inside them. The build tool decides what goes out by prefix: in Vite anything named VITE_, in Next.js anything named NEXT_PUBLIC_. Some keys are meant to travel that way, and a Supabase anon key is one of them. A service_role key, an OpenAI key or a Stripe secret key is not — but an assistant asked to 'make the API call work' will happily move one to the frontend to get past the error.
How to check: Open your deployed site, view source, and search the JavaScript for service_role, sk- and secret. Anything you find there, the whole internet has. Rotate it before you do anything else: a key that has been public stays public, no matter how fast you delete the code.
Reference: Supabase: understanding API keys
Is your database open to anyone who asks?
Supabase and Firebase are unusual in a way that matters here: the browser talks to the database directly, with no server of yours in between. That's what makes them quick to build on, and it means the rules about who may read which row have to live in the database itself. In Supabase that's row-level security. A table with RLS switched off, plus a public anon key, is a table anyone can download in full — that doesn't take an attacker, just curiosity and the network tab.
How to check: In the Supabase dashboard, open the table editor and look for tables with RLS disabled. Then sign out of your own app and try to fetch one of them anyway. If rows come back when nobody is logged in, that's the whole table, to anybody.
Reference: Supabase: row level security
Does the server check who's asking?
Hiding a button is not a permission check. It's very common for the rule to live in the interface — the delete button only renders for admins — while the request behind it will accept anyone who sends it. The interface is a suggestion. Only the server or the database can actually enforce something, and generated code tends to write the suggestion and skip the enforcement.
How to check: Sign in as an ordinary user and change an identifier: a number in the URL, a field in a request. Try to read or edit something belonging to another account. If it works, the check was never there. OWASP has ranked this the number one risk in web applications since 2021, and it's the most common serious problem we find.
Reference: OWASP Top 10: broken access control
Are you keeping more than you need?
Every field you store is something you'd have to explain if it leaked. Phone numbers, addresses, dates of birth, uploaded documents — all easy to collect because the form builder made it easy, all awkward to hold. Passwords you shouldn't be storing at all: that's your auth provider's job, and if your own tables have a password column, something has gone wrong upstream.
How to check: Write out every column you keep about a person. Next to each one, put why you need it and what happens if it ends up on the internet. Delete the ones that fail both. This is the only item on the list that gets easier the earlier you do it.
What happens when it breaks?
It will break. The question is whether you find out from your logs or from a user. Generated code has a habit of catching an error, showing a friendly message and throwing the actual cause away — which is comfortable right up until the morning payments stop working and there's nothing to read.
How to check: Break something on purpose in a copy of your app: revoke a third-party key, or point it at a database that isn't there. Then look for two things. Does the app tell the user something honest instead of showing a blank screen, and is there a record anywhere of what actually went wrong?
Reference: OWASP: what's worth logging, and what isn't
What happens when fifty people show up?
Working for you means one person, on a good connection, against a nearly empty database. Launch-day collapses are usually one of three things: a query that runs once per row instead of once, a table with no index that was fine at 200 rows, or a free tier that stops at a connection limit nobody ever looked up.
How to check: Fill a copy of your database with a realistic amount of data — a few thousand rows, not five — and click around it. Whatever is slow now gets worse in public. While you're there, find the actual limits of the plan you're on.
Can you undo it?
The worst launch days aren't the ones with a security hole. They're the ones where a migration ran against the wrong environment and there's no way back. Backups on a free tier usually go back less far than people assume, and a backup nobody has ever restored is a hypothesis, not a backup.
How to check: Find out how far your backups actually reach, then restore one into a scratch project and see whether it comes up. Do the same for your deploy: work out how you'd put yesterday's version back before that's the thing you need.
Reference: Supabase: backups and how far back they go
So — is it safe?
No page can answer that for your app, and anyone selling you a green tick is selling you the tick. What this list does is separate the two kinds of risk. The first three — keys, row-level security, permission checks — are the ones that end with someone else holding your users' data, and they're worth fixing before you launch rather than after. The rest cost you a bad weekend. None of it requires a security background. It requires an afternoon.
This is general guidance, written from the reviews we do. It isn't an audit of your app, it doesn't cover everything, and the specifics of your stack matter.
Want a second pair of eyes?
We're two software engineers and we do this for free, in plain language, for people building with AI tools. Send us what you're working on and we'll go through the list with you — read-only access, no charge, no pitch at the end.
Tell us about your project