Migration

Firebase to Supabase migration: why teams switch and what actually changes

Firebase to Supabase migration

A practical look at the reasons behind the move, what happens to your data and auth, and how to plan a migration that doesn’t break production.

Firebase is a great way to ship a first version fast. Firestore, Auth, and Storage come pre-wired, and for a prototype or an early MVP, that speed is exactly what you need. The problems tend to show up later — once the data model has real relationships, the bill has real traffic behind it, and the team wants row-level access control instead of a parallel rules language to maintain.

That’s the point where a Firebase to Supabase migration usually enters the conversation. This guide walks through why teams make the move, what actually changes under the hood — data model, authentication, storage, realtime — and how complex the process really is, based on the patterns we see across migrations at Gart Solutions.

TL;DR
01 / Data Model

Firestore’s NoSQL model struggles with relational data and complex queries; Postgres handles both natively, with real joins instead of denormalization workarounds.

02 / Pricing & Scaling

Firebase billing scales with reads, writes, deletes, and bandwidth — which gets unpredictable fast. Supabase’s pricing is flatter and easier to plan against.

03 / Security & APIs

Supabase ships Row Level Security, instant REST and GraphQL APIs, and Realtime on top of standard Postgres — no separate rules DSL to maintain.

04 / Migration Effort

Migration complexity is moderate: reshaping the data model is the hard part, while Auth has an official, well-documented export/import path.

Expert Migration Support

Gart Solutions plans and executes migrations of any complexity — from Firebase specifically, and from the wider Postgres and BaaS ecosystem more broadly.

Why teams are leaving Firebase for Supabase

Firestore wasn’t built for relational data

Firestore is a document database. That’s fine for flat, self-contained records — a user profile, a single chat message — but most real products don’t stay flat for long. Orders reference customers and inventory. Bookings reference venues, staff, and availability windows. The moment your data has real relationships, Firestore forces a choice: denormalize (copy data into multiple documents and keep it in sync by hand) or fan out writes across collections to simulate a join that a relational database gives you for free.

Composite indexes are often the tell. If your Firestore console is full of them, it’s usually a sign the underlying data wants to be relational and is being modeled around a document store instead of with one. Postgres — the database underneath Supabase — handles joins, foreign keys, and multi-table queries as first-class operations, because that’s what it was designed for.

Firebase bills are hard to predict

Firebase’s pricing model charges per document read, write, and delete, plus bandwidth and storage. That’s manageable at low volume, but it means the cost of a feature is only really visible once it’s in production and traffic finds it. It’s a familiar pattern in Firebase communities: an inefficient listener, a missing index, or a feature that goes viral for the wrong reasons can turn a predictable few-hundred-dollar month into a bill an order of magnitude higher, with little warning until the invoice arrives.

Supabase’s pricing is built around compute and storage tiers rather than per-operation billing, which makes it substantially easier to forecast costs as a product scales — and to catch a runaway query before it becomes a runaway bill.

SQL and Row Level Security “out of the box”

Firebase security is enforced through a separate rules language (Firestore Security Rules) that lives outside your schema and has to be kept in sync with it by hand as the app evolves. Supabase takes a different approach: Row Level Security (RLS) policies are written in SQL, live directly on the Postgres tables they protect, and are enforced by the database itself — not by a middleware layer your team has to trust blindly.

On top of that, Supabase auto-generates REST and GraphQL APIs directly from your Postgres schema, so a properly modeled, RLS-protected table is immediately queryable from the client without writing a custom backend layer for it.

What actually happens during a Firebase to Supabase migration

Data: reshaping Firestore documents into Postgres tables

There’s no 1:1 mapping between a Firestore collection and a Postgres table, and that’s the part of the migration that actually takes engineering judgment. Each collection needs a decision: does it become its own table, a foreign-keyed child table, or a JSONB column for genuinely flexible, schema-less fields? Subcollections, arrays of references, and denormalized copies of data all need to be resolved into a coherent relational schema before a single row gets migrated.

In practice, this means exporting Firestore data (typically via the Firebase Admin SDK or a batch export), transforming it against the new schema, and bulk-loading it into Postgres — then validating record counts and referential integrity before cutting traffic over.

A concrete example makes this less abstract. A typical Firestore orders document, denormalized the way Firestore encourages, looks something like this:

{
  "orderId": "ord_8f21",
  "customerName": "Maria Kovalenko",
  "customerEmail": "maria@example.com",
  "items": [
    { "sku": "SKU-100", "name": "Wireless Mouse", "qty": 2, "price": 19.99 },
    { "sku": "SKU-204", "name": "USB-C Hub", "qty": 1, "price": 34.50 }
  ],
  "status": "shipped",
  "createdAt": "2026-06-12T10:04:00Z"
}


Customer details are copied directly into the order because Firestore has no native join — if customerName changes, every past order document with the old name stays stale unless you write a background job to fix it. The equivalent Postgres schema removes that duplication entirely:

create table customers (
  id uuid primary key default gen_random_uuid(),
  name text not null,
  email text unique not null
);

create table orders (
  id uuid primary key default gen_random_uuid(),
  customer_id uuid references customers(id),
  status text not null,
  created_at timestamptz not null default now()
);

create table order_items (
  id uuid primary key default gen_random_uuid(),
  order_id uuid references orders(id) on delete cascade,
  sku text not null,
  name text not null,
  qty integer not null,
  price numeric(10,2) not null
);

Three tables instead of one denormalized document, a real foreign key relationship, and no background job needed to keep customer data in sync. This is the kind of decision that has to be made collection by collection — and it’s the actual engineering work in a Firebase to Supabase migration, not the data transfer itself.

Translating Firestore Security Rules into Postgres RLS policies

The mental shift here is worth spelling out, because it changes how access control is written, not just where. A common Firestore rule looks like this:

match /orders/{orderId} {
  allow read: if request.auth.uid == resource.data.ownerId;
}


The equivalent Supabase RLS policy is SQL, attached directly to the table:

alter table orders enable row level security;

create policy "Users can read their own orders"
on orders for select
using (auth.uid() = customer_id);

Functionally similar, but the enforcement point has moved from an external rules engine to the database itself — which means every client (your app, a script, an admin dashboard, a future integration) gets the same protection automatically, instead of needing to independently respect the same rules logic.

Auth: preserving users and password hashes

Supabase publishes an official Firebase Auth migration path, including an import script that carries over user records and — for compatible authentication methods — existing password hashes, so end users aren’t forced to reset their passwords the moment you cut over. Users who signed in via Google, Apple, or another OAuth provider migrate even more cleanly, since there’s no password hash to carry over at all — just the account record and provider linkage.

Storage and security rules

Files in Firebase Storage move over to Supabase Storage buckets in a fairly direct transfer. The part that needs actual rework is the security layer: Firebase Storage Security Rules have to be rewritten as Supabase Storage RLS policies. The upside is that once that’s done, storage access control uses the exact same policy language and mental model as your database access control — one system instead of two.

Realtime listeners

Firestore’s onSnapshot listeners and Supabase Realtime solve the same problem — pushing live updates to clients — through fundamentally different mechanisms. Firestore uses its own sync protocol; Supabase Realtime is built on Postgres’s logical replication (change data capture). That difference means realtime subscription code on the client needs to be rewritten against Supabase’s API, not just repointed at a new URL.

Cloud Functions and backend glue code

Firebase Cloud Functions fall into two rough categories, and they migrate very differently. HTTP-triggered functions — the ones called directly from your client or a webhook — map fairly cleanly onto Supabase Edge Functions, which also run on-demand, close to the database, without you managing a server. The rewrite is mostly a change of runtime conventions, not of logic.

Firestore-triggered functions — the ones that fire automatically onCreateonUpdate, or onDelete for a document — don’t have a direct equivalent, because that trigger model is specific to Firestore. The Postgres way to get the same behavior is a database trigger calling a function, or a Database Webhook that fires on row changes and calls an Edge Function or external endpoint. It’s the same outcome, but it has to be deliberately rebuilt rather than ported.

How to validate a migration before cutover

A migration that “looks done” and a migration that’s actually safe to cut traffic over to are two different things. The validation step is where that gap gets closed, and skipping it is how silent data loss makes it to production. A reasonably thorough validation pass covers:

  • Row count reconciliation — every migrated table’s row count matches the source collection’s document count, accounting for any intentional filtering or splitting.
  • Spot-check integrity — pull a random sample of records from both systems and compare field-by-field, not just record counts. Aggregate counts can match while individual records are subtly wrong.
  • Referential integrity checks — confirm every foreign key actually resolves (no orphaned order_items rows pointing at an order_id that doesn’t exist).
  • Shadow-read testing — for a window before cutover, run the same read query against both Firestore and Supabase from the application layer and log any mismatches, without serving the Supabase result to users yet.
  • Dual-write monitoring — during a staged cutover, writes go to both systems and get compared continuously, so a discrepancy surfaces before the old system is switched off, not after.

None of this is exotic engineering — it’s the same discipline any production data migration needs, regardless of source or destination. It’s just easy to skip under deadline pressure, which is exactly when it matters most.

How long does a migration actually take

Complexity, not data volume, is the real driver of migration timelines. As a rough guide, based on the pattern of projects we scope at Gart Solutions:

Project size Typical scope Rough timeline
Small Few collections, mostly flat documents, OAuth-heavy auth, tolerant of a maintenance window 1–2 weeks
Medium Moderate relational structure, mixed password/OAuth auth, some custom Cloud Functions, staged cutover required 3–6 weeks
Large Deep relational data, heavy Security Rules logic, high-traffic production system, zero-downtime requirement 6–12+ weeks

These ranges assume the schema design work happens up front rather than mid-migration — which is the single biggest lever on whether a project lands in the low or high end of its bracket.

How complex is a Firebase to Supabase migration, really?

Component Complexity Why
Data model Moderate–High No 1:1 mapping from Firestore collections to Postgres tables; requires real schema design
Authentication Low–Moderate Official export/import tooling exists; password-based users need hash migration, OAuth users migrate cleanly
Storage Low Files transfer directly; security rules need to be rewritten as RLS policies
Realtime Moderate Different underlying mechanism (sync protocol vs. Postgres replication); client code needs rework

Taken together, the honest answer is: moderate. The data migration from Firestore’s NoSQL model into a relational schema is the piece that needs the most thought, while authentication is comparatively well-trodden ground thanks to Supabase’s official scripts. Neither part is trivial, but neither is a research project — this is a well-understood migration path with documented tooling on both ends, not an unmapped one.

Common pitfalls we see

  • Treating it as a lift-and-shift. A Firebase to Supabase migration is a data modeling project first and a data moving project second. Skipping the schema design step to move faster usually means redoing it later, under worse conditions.
  • Underestimating how much logic lives in Security Rules. Firestore rules often quietly encode business logic, not just access control. That logic needs to be found and accounted for, not just translated line by line.
  • No staged cutover plan. Migrating a live, actively-used database without a dual-write window or a clear rollback point is how “weekend migration” turns into “week-long incident.”
  • Ignoring what your composite indexes are telling you. If Firestore needed a composite index to make a query work, that’s usually a preview of exactly where your new Postgres schema needs a proper join.

A quick pre-migration checklist

Before scoping a Firebase to Supabase migration, it’s worth answering these questions honestly — they tend to predict how smooth the project will be far better than data volume does:

  • How many collections have deep relational structure (references to other collections, denormalized copies of data) versus how many are genuinely flat, self-contained documents?
  • How much business logic is embedded in Firestore Security Rules, beyond simple “is this user the owner” checks — conditional writes, rate limiting, cross-document validation?
  • What percentage of your users authenticate via email/password versus OAuth providers? This directly affects how much of your Auth migration is a clean import versus a hash-compatibility exercise.
  • Can the application tolerate a staged cutover, or does it need a hard switch at a specific moment? This shapes whether a dual-write window is realistic or whether you’re planning around a maintenance window instead.
  • Are there Cloud Functions or other Firebase-specific glue code that will need to be reimplemented as Supabase Edge Functions or moved elsewhere entirely?

None of these questions have a “wrong” answer — they just change the shape of the migration plan. A team with mostly flat collections, mostly OAuth users, and tolerance for a staged cutover is looking at a materially simpler project than one with deep relational data, password-heavy auth, and a hard cutover requirement. Scoping this honestly up front is what keeps a migration on schedule.

Planning a production migration, not a side project?

Gart Solutions runs zero-downtime cloud migrations for teams moving off Firebase and onto Supabase — including schema design, Auth cutover, and RLS setup.

How Gart Solutions approaches these migrations

A Firebase to Supabase migration touches data modeling, authentication, security policy, and often the client application itself — which is exactly why we treat it as an engineering project with a plan, not a weekend script. Our process typically covers:

  • Schema design — turning Firestore collections into a properly normalized (or deliberately denormalized, where it makes sense) Postgres schema
  • Auth migration — carrying over users and password hashes where possible, with a clear path for OAuth-based accounts
  • Row Level Security — building the RLS policy set that replaces Firestore Security Rules, table by table
  • Zero-downtime cutover — staged migration and dual-write windows for production systems that can’t afford an outage

Just as important: we handle migrations of any level of complexity, not only from Firebase. The same team that plans a Firestore-to-Postgres schema redesign also runs migrations from Amazon RDS, Neon, Heroku, Render, and legacy MySQL or MSSQL databases onto Supabase — and, where it’s the right call for a client, migrations away from Supabase too. If your source system isn’t Firebase, the underlying question is usually the same one: what’s the safest path from where your data is now to where it needs to be, and how do you get there without breaking production.

Conclusion

Firebase gets you moving fast, and for plenty of products, it stays the right choice for a long time. But once your data has real relationships, your bill has real traffic behind it, and your team wants access control that lives in the database rather than a parallel rules layer, a Firebase to Supabase migration starts to look less like an experiment and more like a fix. The migration itself is moderate in complexity, well-documented on the tooling side, and — with the right schema design up front — doesn’t have to touch production uptime at all.

Planning a Supabase or Postgres migration?

Gart Solutions’ database migration engineers plan and execute Postgres migrations — into Supabase, within a live schema, or off a managed platform entirely — with a rollback plan built in from day one, not bolted on after something breaks.

40% cost reduction on a comparable Postgres migration
25% query performance improvement
Minimal downtime during cutover
Database Migration Cloud Migration SRE & Monitoring Compliance Audit
Talk to a migration engineer  →
Let’s work together!

See how we can help to overcome your challenges

FAQ

Is it hard to migrate from Firebase to Supabase?

It's a moderate-complexity migration, not a trivial one. The hardest part is reshaping Firestore's NoSQL document model into a relational Postgres schema, since there's no automatic 1:1 mapping. Authentication is comparatively straightforward thanks to Supabase's official Firebase Auth import tooling. Storage and realtime each need some rework, but neither is a research project — this is a well-documented path.

Can I migrate Firebase Authentication users to Supabase without forcing a password reset?

In many cases, yes. Supabase's official Firebase Auth migration path includes an import script that can carry over existing password hashes for compatible authentication methods, so users don't have to reset their password immediately after cutover. Users who signed in via Google, Apple, or another OAuth provider migrate even more cleanly, since there's no password hash involved at all.

How long does a Firebase to Supabase migration take?

It depends almost entirely on how complex your data model is and how much logic lives inside your Firestore Security Rules — not on data volume alone. A small app with a simple schema can move in days; a production system with deep relational structure and custom rules logic can take several weeks of design and testing before cutover. Gart Solutions scopes this during an initial technical audit before committing to a timeline.

What happens to my Firestore Security Rules?

They get rewritten as Supabase Row Level Security (RLS) policies, in SQL, attached directly to your Postgres tables. This is more than a syntax change — RLS is enforced by the database itself, and Firestore rules often encode business logic beyond simple access control, so each rule needs to be reviewed and translated deliberately rather than copied line by line.

Does Supabase support real-time updates like Firestore?

Yes, through Supabase Realtime, which is built on Postgres's logical replication rather than Firestore's own sync protocol. The end result — clients receiving live updates when data changes — is similar, but the client-side subscription code is different and needs to be rewritten against Supabase's Realtime API, not just repointed at a new endpoint.

Is Supabase cheaper than Firebase?

It depends on your usage pattern, but Supabase's compute-and-storage-tier pricing is generally easier to forecast than Firebase's per-read/write/delete model. Teams often move not because Supabase is guaranteed to be cheaper at every scale, but because the bill stops being a surprise — a spike in traffic doesn't translate directly into a spike in cost the way it can on Firebase's usage-based billing.

Can Gart Solutions migrate a large, actively-used production database without downtime?

Yes — zero-downtime migration is standard practice in our cloud migration engagements. For production systems, we typically plan a staged cutover with a dual-write window, so the source and destination stay in sync until we're confident enough to switch traffic over completely, with a clear rollback point if anything looks wrong.

What tools are typically used for a Firebase to Supabase migration?

On the export side, the Firebase Admin SDK (or a batch export) pulls data out of Firestore. The transform step is usually custom code, since schema design decisions are project-specific and don't fit a generic tool. On the import side, Postgres's native bulk-loading tools handle getting data in efficiently, and Supabase's official Auth migration script handles user and password-hash import. For most real projects, the transform logic is the part that has to be purpose-built rather than pulled off the shelf.

Can I migrate Firebase Cloud Functions to Supabase?

HTTP-triggered Cloud Functions generally port over to Supabase Edge Functions without too much friction, since both run on-demand without server management. Firestore-triggered functions (onCreate, onUpdate, onDelete) don't have a direct equivalent — they need to be rebuilt as Postgres database triggers or Database Webhooks that call an Edge Function when a row changes. The behavior is reproducible, but it has to be deliberately reimplemented, not copy-pasted.

Do I need to migrate everything at once, or can it be done incrementally?

It depends on how coupled your collections are. Genuinely independent parts of the data model — a notifications collection with no relational ties to the rest of the schema, for example — can sometimes move in an earlier phase. But collections with real relationships (orders, customers, inventory) generally need to move together, since splitting them across two live databases mid-migration creates exactly the kind of sync problem Postgres was supposed to eliminate. Gart Solutions scopes this phase-by-phase during the initial technical audit.

What other platforms can Gart Solutions help migrate to or from Supabase?

Beyond Firebase, we regularly handle migrations from Amazon RDS, Neon, Heroku, Render, and legacy MySQL or MSSQL databases onto Supabase, as well as migrations away from Supabase when that's the right call for a client's scale or compliance needs. The common thread across all of them is the same engineering discipline: schema design, a tested cutover plan, and no surprises in production.
arrow arrow

Thank you
for contacting us!

Please, check your email

arrow arrow

Thank you

You've been subscribed

We use cookies to enhance your browsing experience. By clicking "Accept," you consent to the use of cookies. To learn more, read our Privacy Policy