Supabase vs Firebase: two opposite ways to be exposed

Both platforms hand your database a public key and put a rules layer in front of it. That is where the similarity stops. Firebase evaluates rules in front of the datastore and rejects whole queries; Supabase evaluates policies inside Postgres and quietly removes rows. The consequence is that one tends to fail loudly during development and the other tends to fail silently in production — and that shapes what you have to watch.

Short answer

Neither Supabase nor Firebase is more secure than the other, but they fail in opposite directions. Supabase Row Level Security filters rows silently, so a broken policy returns an empty list or shows the wrong data with no error, while Firestore Security Rules reject the entire query instead and break visibly during development.

Firebase's insecure default expires: test mode is wide open but stops serving after 30 days. Supabase's historical default did not expire — tables in the public schema received API grants automatically and stayed reachable indefinitely. From 30 October 2026 that changes for existing Supabase projects too.

Supabase RLS vs Firestore Security Rules at a glance

 SupabaseFirebase
BoundaryRow Level Security, inside PostgresSecurity Rules, in front of Firestore
Written inSQL boolean expressionsPurpose-built rules language
On denialFilters rows silently, query succeedsRejects the whole query with an error
Applies toEvery client of the databaseSDK access; Admin SDK bypasses it
Insecure defaultAutomatic API grants, never expiredTest mode, expires after 30 days
FailsOpen and silentClosed and loud
Bypass credentialservice_role JWT stringAdmin SDK service account file
Public client keyanon key — not a secretWeb API key — not a secret
Audit trailSQL statements in Postgres logsVersioned rules deploys
Testing toolingSQL tests, role impersonationRules emulator and unit tests

Where the security boundary lives in each

In Firebase, Security Rules sit between the client and Firestore. They are written in a purpose-built language, deployed as their own artifact, and evaluated per request against the document being touched. The rules are not part of your data; they are a gate in front of it.

In Supabase, the boundary is the database. Row Level Security policies are SQL expressions attached to tables and enforced by Postgres itself, so they apply no matter what speaks to the database — PostgREST, a direct connection, a background job. Nothing routes around them except a role explicitly allowed to bypass.

Both designs are defensible. The Supabase one gives you a single enforcement point and the full expressiveness of SQL. The Firebase one gives you a boundary you can version, test and deploy independently of your schema. The trouble is that each design has a characteristic way of going wrong, and they are near opposites.

Why Firestore Rules reject queries and RLS filters rows

This is the difference that catches people migrating in either direction.

Firebase Security Rules are not filters. If a query could return a single document the caller is not permitted to read, Firebase rejects the whole query. You do not get a partial result — you get an error. The practical consequence is that your queries have to be shaped so they can only ever ask for what the rules already allow, which is why Firebase developers end up writing where("ownerId", "==", uid) into queries that the rules would enforce anyway.

Supabase RLS is a filter. The query succeeds and the rows you are not allowed to see simply are not in the result. A SELECT against a table whose policy denies you returns HTTP 200 and an empty array, which is byte-for-byte identical to the response for a table that is genuinely empty.

So the same mistake produces opposite symptoms. On Firebase, a policy that is too strict breaks your app immediately and you fix it before you ship. On Supabase, a policy that is too strict shows an empty list, and a policy that is too loose shows the right data to the wrong person — neither of which raises anything. Reads are the blind spot; writes at least fail loudly with SQLSTATE 42501.

Default security: test mode, locked mode, and automatic grants

When you create a Firestore database you pick locked mode, which denies everything, or test mode, which is allow read, write: if true — completely open to anyone on the internet. Test mode is the dangerous one, with an important mitigation: it expires after 30 days and then denies everything. A project someone spun up and forgot breaks in an obvious way rather than quietly serving your data for a year. Both modes are set out in Firebase's rules documentation.

Supabase historically failed the other way. Every new table in the public schema received grants for the anon and authenticatedroles automatically, so it was reachable through the Data API from the moment it existed. RLS was the only thing standing in front of it, and RLS is enabled by default only for tables created through the dashboard's Table Editor — not for tables created in the SQL editor or by a migration, which is how most tables in a real project get made. Nothing expired. Nothing warned. The table simply stayed public.

That asymmetry — a temporary insecure default that fails closed, versus a permanent one that fails open — is the most consequential difference between the two platforms to date.

What changes on 30 October 2026

Supabase is closing exactly that gap. Tables in the public schema are no longer exposed to the Data API and GraphQL API automatically; access has to be granted explicitly:

grant select on public.your_table to anon;
grant select, insert, update, delete on public.your_table to authenticated;

The rollout has three dates, per Supabase's changelog. From 28 April 2026 it was available as an opt-in toggle at project creation. From 30 May 2026 it became the default for all new projects. From 30 October 2026 it is enforced on existing projects too.

If your project predates that and leans on the automatic grants, this is a breaking change with a deadline: endpoints that work today will start failing. It is worth finding out now which of your tables are exposed by inherited grants rather than by a decision anyone made.

service_role vs the Firebase Admin SDK

Both platforms have a credential that ignores the rules entirely, and the difference is in how easy each one is to leak by accident.

Supabase's service_role key is a JWT — a string, sitting in the same dashboard page as the anon key, looking almost identical to it. It goes in an environment variable. Give that variable a NEXT_PUBLIC_ or VITE_ prefix and your bundler compiles a key that bypasses every policy you wrote straight into a file you serve to the public.

Firebase's equivalent is the Admin SDK, authenticated with a service account JSON file you download. Also catastrophic if it leaks, but a file that has to be read from disk or an environment secret is meaningfully harder to paste into client code than a string that looks exactly like the one that belongs in client code.

Firebase's public Web API key causes the mirror-image confusion: people find it in their bundle and panic. It is not a secret, exactly as Supabase's anon key is not a secret. On both platforms, the key is not the boundary. The rules are.

What each platform lets you see after something goes wrong

Firebase's rules are a deployed artifact with version history, so you can see that the gate changed and roll it back. What you get less of is a queryable record of individual denials as they happen.

Supabase's boundary changes are ordinary SQL statements, which means they land in your Postgres logs as text you can search, attribute and alert on. ALTER TABLE ... DISABLE ROW LEVEL SECURITY is right there, with the role that ran it. Denied writes appear as SQLSTATE 42501. Denied reads appear as nothing at all, because they were filtered rather than rejected — which is the one place Firebase's reject-the-query model is genuinely easier to observe.

The practical summary: on Supabase you can reconstruct what happened from your logs, but only if something is reading them. Nothing does that by default.

Is Firebase more secure than Supabase?

Neither list makes one platform the safe choice. They describe two different jobs. On Firebase the job is writing rules carefully and testing them. On Supabase the job is writing policies carefully — and then noticing when something changes them.

What to watch on Supabase

How Defencecore fits

Defencecore reads your Supabase auth and Postgres logs continuously and opens an incident when a detection rule matches — including the moment row level security is switched off on a table, which is the single change most likely to turn a private table public. Each incident carries the raw log lines that triggered it, so you can confirm or dismiss it without reconstructing anything.

It is read-only. It holds no path that can alter your project, which is the same reasoning that should make you cautious about anything else you connect to production.

Frequently asked questions

Is Firebase more secure than Supabase?
Neither is more secure. They fail differently, and the difference matters more than the ranking. Firebase's insecure starting position is time-limited and fails closed — test mode stops serving requests after 30 days, so a forgotten project breaks loudly. Supabase's historical starting position failed open: a table with grants and no RLS stayed readable indefinitely and nothing complained. Supabase is closing that gap, but the failure modes still differ, and so should how you watch each one.
Is the Supabase anon key the same as the Firebase API key?
In the sense that matters, yes: both are designed to ship in a browser bundle and neither is a secret. Firebase's docs say so explicitly, and Supabase's anon key is a signed JWT meant to be public. In both cases the key identifies your project, and the actual security boundary is the rules layer — Firebase Security Rules or Postgres Row Level Security. Finding either key in a bundle is not a leak.
Do Firebase Security Rules filter query results?
No, and this is the single most misunderstood thing about them. Rules authorise a query, they do not filter it. If a query could return one document the caller is not allowed to read, Firebase rejects the entire query rather than returning a subset. You have to constrain the query so it can only ask for what the rules already permit. Supabase RLS does the opposite: it silently filters rows out of an otherwise successful query.
What happens to Supabase projects on 30 October 2026?
Tables in the public schema stop being exposed to the Data API and GraphQL API automatically. New projects have worked this way since 30 May 2026; on 30 October 2026 it is enforced on existing projects too. After that, a table is reachable through the API only if you have explicitly granted privileges to the anon or authenticated role. If your app relies on the old automatic grants, endpoints that work today will start returning errors.
Can I reuse my Firebase Security Rules if I migrate to Supabase?
No. They are different languages enforcing different things in different places. Firebase Rules are a purpose-built DSL evaluated per document request; RLS policies are SQL boolean expressions evaluated per row inside Postgres. The logic often translates conceptually, but every rule has to be rewritten, and the query-shape assumptions do not carry over at all.