migration guide
Firebase to Supabase
the data moves fine. the hard part is that firestore is a document store and postgres is relational, so you're redesigning your schema, not copying it — and every query in your app gets rewritten. auth migrates with password hashes intact, which is the part people expect to be worst.
- difficulty
- hard
- time
- 1-2 weeks
- official tool
- Supabase tooling
- reversible
- no
biggest risk
treating this as a data transfer. firestore's denormalised documents have no direct postgres equivalent — the nested collections and duplicated fields that made firestore fast are exactly what you must undo. the schema redesign is the project; the data copy is an afternoon.
the data copy is not the project
Almost every guide to this migration walks you through exporting Firestore to JSON and loading it into Postgres. That part is an afternoon.
The project is that Firestore and Postgres want opposite things from your data.
Firestore is a document store where denormalisation is correct. Duplicating a user's name across every order document is the right call — it's how you avoid joins and keep reads fast. Postgres is relational and wants that normalised: one users table, one orders table, a foreign key between them.
So a literal copy produces a Postgres database shaped like Firestore. It works, it performs badly, and it throws away the main reason to move. The schema redesign is the migration. Do it on paper before you export anything.
the part that's easier than you expect
Auth. Firebase exports users with their password hashes, and Supabase imports them. Your users keep their passwords and never see a forced reset.
This is worth stating plainly because fear of a mass password reset stops a lot of teams from ever starting. It isn't a risk here. Test the hash format on a handful of accounts first, then do the rest.
security rules are not a port, they're a rewrite
Firestore security rules and Postgres Row Level Security solve the same problem with completely different models. There's no converter and there shouldn't be.
Two failure modes to know about, because they fail in opposite directions:
- A table with RLS enabled and no policy blocks everything. Your app breaks loudly, which is the safe failure.
- A table with RLS not enabled is readable by anyone holding your anon key — which is a public key, in your frontend bundle. Your app works perfectly and your data is exposed, which is the dangerous failure.
The second one is silent. Enumerate every table and confirm its policy explicitly. Don't infer from the app working.
what actually changes on the bill
Supabase typically lands 30–50% cheaper at mid scale, but the structural difference matters more than the percentage.
Firebase prices operations — every document read, write and delete. Your bill tracks how chatty your app is, and a bad query in a loop is a genuine financial event.
Supabase prices resources — database size, storage, monthly active users. Pro is $25/month per organisation, not per project, which is the single most commonly misreported fact about Supabase pricing. The spend cap is on by default.
For a team that has ever been frightened by a Firebase invoice, the predictability is often worth more than the savings. Full detail in the Supabase vs Firebase comparison.
do it in pieces
The failure pattern is a big-bang cutover: redesigned schema, rewritten queries, new auth and a new security model, all switched at once on a live app.
Instead, move one feature's data at a time, or dual-write to both backends during a transition. Keep Firebase live and readable for a month after you cut over — the cost of a parallel month is trivial against the cost of discovering a transformation bug with no source to re-run from.
And run your transform script against staging repeatedly. You will change the schema after seeing real data in it. Everyone does.
still deciding whether to move at all?
read Firebase vs Supabase →frequently asked
newsletter
one verdict a week.
new comparisons, stack updates, and the occasional rant. free forever.
last updated: september 24, 2026