Migrating from Firebase to Supabase means moving four things rather than one: your Firestore data into Postgres tables, your Firebase Auth users into Supabase Auth, your storage files, and, most importantly for security, your access rules from Firebase Security Rules to Supabase Row Level Security. Supabase provides an open-source migration toolset and official guides that handle the data and user parts, and you can bring users across with their existing passwords rather than forcing a reset. The step you cannot skip is re-implementing your access control as Row Level Security and enabling it on every table before you import data, because an unsecured Postgres table is public in a way a Firestore collection governed by rules is not.
Short answer
The migration has four parts, and one of them is a security rewrite you must not overlook. Per Supabase's Firestore migration guide, you export your Firestore documents and load them into relational Postgres tables, flattening or splitting nested data. Per Supabase's Auth migration guide, tools export your Firebase Auth users and import them into Supabase's auth.users, and you can preserve passwords using Firebase's password hash parameters or a first-login middleware. The critical difference is access control: Firebase Security Rules become Supabase Row Level Security policies, which you must enable on every table before importing, or the data is public.
What migrating actually involves
A Firebase-to-Supabase migration is really four migrations plus a code change, and treating it as a single copy is where people go wrong. You move Firestore data from a NoSQL document store into a relational Postgres database, you port your Firebase Auth users into Supabase Auth, you move files from Firebase Storage into Supabase Storage, and you re-implement your Firebase Security Rules as Row Level Security policies. Then you update your app to call the Supabase client instead of the Firebase SDK.
The reason to see it as separate pieces is that they have different tools and different risks. The data and user moves are largely mechanical with Supabase's tooling, the storage move is a file copy, but the security rewrite is a genuine reimplementation because the two platforms enforce access completely differently. So plan the migration as these distinct tracks, and give the security rewrite the most attention, since it is the part that a tool cannot do for you and the part where a mistake exposes data.
Migrate your Firestore data to Postgres
The data migration is a model change, not just a copy, because Firestore is schemaless documents and Postgres is relational tables. You export your Firestore collections and load them into tables, and along the way you design a schema: deciding which fields become columns, how to handle nested objects, and what to do with subcollections. Supabase's tooling lets you customize the export, and a common step is to flatten nested JSON or split it into separate, related tables, though you can also keep flexible data in a jsonb column.
So the work here is thinking through your data model rather than running one command. Denormalized Firestore documents often map to several related tables with foreign keys, and choosing that structure well is what lets you use Postgres features like joins and constraints afterward. Take the migration as an opportunity to define a real schema, since carrying a document blob straight into a single table works but gives up much of what you moved to Postgres for. Once the schema is set, the export tool populates the tables.
Port your Firebase Auth users
You can bring your Firebase Auth users into Supabase Auth without forcing everyone to reset their password, which is usually the biggest worry. Supabase provides tools to export users from Firebase to a JSON file and import them into the auth.users table of your Supabase Postgres instance. To preserve passwords, you retrieve your Firebase project's password hash parameters, the signer key, salt separator, rounds, and memory cost from the Firebase Console, so Supabase can validate the existing hashes, since Firebase uses a scrypt-based scheme.
There is an alternative for a smoother experience, which the migration tooling documents. You can run a middleware component that, the first time each user logs in, verifies their existing Firebase password and then updates it in Supabase, migrating users gradually as they sign in. Either way, the goal is that users keep their credentials, so choose the bulk hash-parameter import if you want everyone moved at once, or the first-login middleware if you prefer a gradual, transparent migration. What you avoid in both cases is a mass password reset.
What migration tools does Supabase provide?
Supabase maintains an open-source firebase-to-supabase toolset alongside its official migration guides, so you are not building the migration from scratch. For users, the tools export your Firebase Auth accounts to a JSON file and then import them into Supabase, inserting them into the auth.users table. For data, the tooling exports Firestore collections and lets you shape the output with a custom hook to flatten or restructure nested documents into tables. There is also guidance for moving files from Firebase Storage to Supabase Storage.
So the practical toolkit covers the mechanical parts of the migration: users, data, and storage each have a supported path. What the tools deliberately do not do is design your schema or write your security policies, because those are decisions specific to your app. So use the Supabase tooling for the heavy lifting of moving records and files, and reserve your own effort for the schema design and the Row Level Security rewrite, which are the parts that shape whether the result is correct and safe.
Rewrite security: Firebase Rules become Row Level Security
This is the part that most affects safety and cannot be copied over: Firebase Security Rules and Supabase Row Level Security are different mechanisms, so you reimplement your access control rather than migrate it. Firebase Rules are declarative rules attached to your database that gate reads and writes per path. Supabase enforces access with Row Level Security policies written in SQL on your Postgres tables, defining what each role can select, insert, update, and delete, commonly keyed on the authenticated user with a pattern like auth.uid() equals the row's user id.
The danger during migration is the default. A Postgres table without Row Level Security enabled is fully readable and writable by anyone with your public API key, which is the opposite of a Firestore collection that a rule was protecting. So you must enable Row Level Security on every table and write policies before you import data and expose the tables, not after. Doing it in the wrong order, or forgetting a table, is exactly how migrated apps end up with public data, so treat enabling and testing RLS as a required step of the migration rather than a follow-up.
Firebase Rules versus Supabase RLS at a glance
The two enforce access differently, which the table below summarizes so you can translate your rules.
| Aspect | Firebase Security Rules | Supabase Row Level Security |
|---|---|---|
| Where it lives | Rules attached to the database | SQL policies on each table |
| Default without it | Denies by default in locked mode | Table is public until RLS is enabled |
| Unit of control | Document paths and collections | Rows in a table, per operation |
| Identity check | request.auth | auth.uid() in a policy |
| How you write it | Rules language | SQL policies |
Read the second row as the migration trap: you must actively enable Row Level Security on Postgres tables, because unlike locked Firestore, an unprotected table is open.
Rewrite your client code
The final piece is your application code, since it currently speaks the Firebase SDK and must call the Supabase client instead. Data access changes from Firestore document and collection reads to Supabase queries against Postgres, which are relational and go through Supabase's API. Authentication calls change from Firebase Auth methods to Supabase Auth, and file access moves to the Supabase Storage client.
This is mechanical but broad, because it touches everywhere your app reads or writes data or handles sign-in. So plan to work through your data and auth calls systematically, testing each against the new backend, ideally after the schema and RLS policies are in place so you are validating against the real access rules. Doing the code change last, once data, users, and security are set up in Supabase, lets you point the app at a backend that is already correct rather than debugging the move and the rules at the same time.
Migration checklist
Working through these steps migrates cleanly and safely. The checklist below covers them.
| Step | Action | Done? |
|---|---|---|
| Design the schema | Map Firestore documents to Postgres tables | [ ] |
| Enable and write RLS | Turn on Row Level Security before importing | [ ] |
| Migrate the data | Export Firestore and load the tables | [ ] |
| Port the users | Import Auth users, preserving passwords | [ ] |
| Move storage | Copy files to Supabase Storage | [ ] |
| Rewrite the client | Swap the Firebase SDK for the Supabase client | [ ] |
The step teams skip most is enabling Row Level Security before importing, since a Postgres table left without it is public, which is the leading way a migrated app leaks data.
Where a scan fits
A migration changes your whole security model, so once you are on Supabase it is worth verifying that the new setup is actually locked down rather than assuming the move preserved your protection.
A scanner like PTKD.com analyzes your app build and flags issues such as an exposed service key, over-broad permissions, and client-trusted access that should be enforced server-side, mapped to OWASP MASVS. To be clear about the boundary: PTKD does not run your migration or write your Row Level Security policies, which are your Supabase setup. It helps you confirm, after the move, that you are not shipping a secret in the app and that access is enforced, which is exactly where a Firebase-to-Supabase migration most often goes wrong.
What to take away
- Migrating from Firebase to Supabase means moving data, auth users, storage, and access rules, then rewriting your client code, not a single copy.
- Firestore documents become Postgres tables, so design a schema and flatten or split nested data rather than dumping a document blob into one column.
- You can port Firebase Auth users with their passwords using Firebase's hash parameters or a first-login middleware, avoiding a mass reset.
- Supabase provides an open-source firebase-to-supabase toolset and guides for the data, user, and storage moves, but not for your schema or security.
- Firebase Rules become Supabase Row Level Security, which you must enable on every table before importing or the data is public, and a tool like PTKD.com helps confirm the new setup is locked down.


