Migrate from Firebase to Supabase

Moving from Firebase to self-hosted Supabase means converting Firestore documents into Postgres tables, importing Auth users with their scrypt parameters and rebuilding security rules. This page plans that work before cutover.

On this page

Migrate from Firebase to Supabase: what the move involves

If a renewal, a billing change, a residency requirement or lock-in is pushing you off Firebase, plan for the rework rather than the export. Supabase documents scripts for Firestore data, Firebase Auth users and Firebase Storage files, but the data model, the client SDK and the access rules all change, so most of the effort and risk sits in application code and policy design. The scripts move the bytes; they do not convert your app. The work is usually done by internal engineers, with an implementation partner brought in for the parts that are hard to staff in-house. Expect the backend engineers to map each Firestore collection to a Postgres table with text, numeric, boolean or jsonb columns, with the migration scripts supporting custom hooks that rename keys or split nested data into related tables. The client team rewrites queries against PostgREST and rebuilds each rule as Postgres row level security. Ask the team to inventory every collection and every security rule before estimating anything, because that inventory sets the scope.

Auth needs its own check. The Supabase guide exports users with the Firebase CLI and inserts them into auth.users after you save the project's scrypt hash parameters from the Firebase console. Confirm with the firebase-to-supabase repository's auth README whether the middleware that verifies existing passwords on first login is ready for your hosting option, because that README marks it as work in progress and lists the password update step as still to be done. Plan for password resets or a staged login flow until you have tested it. Finally, self-hosted Supabase is community-supported through GitHub Discussions, GitHub Issues, Discord and Reddit, and enterprises are directed to contact Supabase's Growth Team. You will own upgrades, backups, secrets and monitoring, and the Docker configuration ships pinned upstream service versions that your operators pull and recreate themselves. Decide who owns that work, and whether a retainer covers it, before cutover.

Which Firebase capabilities map cleanly to Supabase and which need rework

This table compares each Firebase capability with its closest self-hosted Supabase counterpart and marks it clean, needs rework or gap. Read the status column first, then the notes, to see where client code, data design or operations change before cutover.

Firebase capabilitySupabase equivalentStatus and what to plan
Cloud FirestorePostgres tables through PostgRESTNeeds rework. Firestore is a NoSQL document database, while Supabase gives each project a Postgres database. The Firestore migration flattens collections into tables, so nested data and subcollections need a modeling decision.
Firebase AuthenticationSupabase Auth (auth.users)Clean for password users if hashes move. Firebase uses scrypt with project parameters, which you save from the Firebase console and reuse during import. Social provider links and sessions need re-linking and testing.
Cloud Storage for FirebaseSupabase Storage bucketsNeeds rework. Files move with the documented download and upload scripts, but a missing target bucket is created as non-public, so access policies must be rebuilt afterward.
Cloud Functions for FirebaseEdge Functions on the Edge RuntimeNeeds rework. Edge Functions run on Deno, so Node-based function code, triggers and SDK calls must be rewritten and tested.
Realtime Database (JSON tree)Supabase Realtime over PostgresNeeds rework. Subscriptions move to database change streams, but the JSON tree must be redesigned as tables before clients can subscribe to changes.
Firebase HostingHosting outside SupabaseGap. Supabase does not host your web front end in this stack, so plan separate static hosting and custom domains with TLS.
Branching, managed backups and point-in-time recoverySelf-hosted operator toolingGap. Self-hosted Supabase does not include branching, managed backups or PITR, so your team must define and test its own backup and restore process.

How to export Firestore, Auth users and Storage files

Supabase's documented Firebase path splits into three workstreams: Firestore data, Auth users and Storage files. Each runs through its own scripts in the supabase-community firebase-to-supabase repository, and each leaves manual checks that decide whether the cutover works.

Firestore collections to Postgres tables

The first script, collections.js, lists the collections in the Firebase project. firestore2json.js then dumps one collection to JSON, and json2supabase.js loads it into Postgres with a primary key strategy: uuid, bigserial or firestore_id. Choose the key strategy before loading, because it sets how existing references resolve later. Each collection flattens into one table with text, numeric, boolean or jsonb columns, so check every field type on a sample document before running the full load.

Custom hooks for keys and nested data

The Firestore path uses custom hooks where the default flattening does not fit your data model. Hooks can rename keys, calculate derived values, or split nested maps and arrays into related tables. Plan these hooks per collection and write them as code you review, since a renamed key that a client app still reads will break after cutover. Test each hook against a copy of the data and compare row counts with the source collection.

Auth users and scrypt parameters

The Auth path runs firestoreusers2json.js to export users, then import_users.js to insert them into the auth.users table. Before exporting, save the Firebase project's scrypt hash parameters from the Firebase console, because the import needs them to validate existing passwords. Missing or wrong parameters are the most common cause of users being locked out after cutover. Confirm the parameters on a test account before importing the full user base.

Password verification middleware is unfinished

The firebase-to-supabase auth README marks its middleware for verifying existing Firebase passwords on first login as work in progress. The step that rewrites the password into Supabase is also still marked as to be done for every hosting option. Treat password-preserving login as unproven: test it on a staging project, and plan a fallback such as a forced reset email for users whose hashes fail to verify.

Storage files and bucket visibility

The Storage path uses download.js to copy files from the Firebase bucket to local disk, then upload.js to send them to a Supabase bucket. If the target bucket does not exist, the script creates it as non-public. Set bucket access policies after the upload and verify them with a signed-in and a signed-out request. Files that were public in Firebase will otherwise return access errors in the client app.

Reconcile counts before cutover

Run the three paths in a staging project, then compare document counts, user counts and file counts with the Firebase source for each collection and bucket. Record every mismatch with its cause, such as a skipped document or a rejected hash. This reconciliation log is also the evidence you will need to show data integrity to reviewers, and it tells you which gaps must be fixed before the production run.

Migration sequence from inventory to decommission

This sequence moves Firestore data, Auth users and Storage files from Firebase into a self-hosted Supabase stack in controlled stages, with a written output at each gate so cutover and decommission rest on evidence rather than assumption. Each step names the artifact that proves it is finished.

  1. Inventory collections, users, buckets and rules

    List every Firestore collection and subcollection, every Auth provider and user count, every Cloud Storage bucket, and every security rule set in the Firebase project. Record the Firestore location and the Auth sign-in methods, and save the Firebase Auth scrypt hash parameters from the Firebase console, since the Auth import depends on them. Capture which client SDK calls each screen uses. The output is a table mapping each Firestore collection to a planned Postgres table, with a column for the key strategy (uuid, bigserial or firestore_id), plus an inventory of users, buckets and rules. The step is done when the product owner and a developer have both signed off that the inventory is complete.

  2. Design the target schema and access rules

    Convert the document model into relational tables. Decide where nested maps become jsonb columns and where they split into related tables, and write the custom hooks that rename keys or derive values. Translate each Firebase security rule into a Postgres row level security policy and test it against the schema. The output is a schema migration file set and a rules matrix showing, for each table and role, who can read, insert, update and delete. The step is done when every Firebase rule has a matching policy or a documented reason it was dropped.

  3. Run a pilot import into self-hosted Supabase

    Stand up a non-production self-hosted Supabase using the Docker Compose method in your own infrastructure, and replace the placeholder secrets before first start. Run collections.js, firestore2json.js and json2supabase.js against one representative collection, then import a sample of users with firestoreusers2json.js and import_users.js. Download a sample of Storage files with download.js and upload them with upload.js, then set bucket access, since a bucket created by the script is non-public. The output is a user import report listing imported, skipped and failed records, a row count reconciliation per table, and a list of missing or malformed fields. The step is done when counts match the Firebase export for the pilot set.

  4. Test password logins and client code paths

    Confirm that imported users can sign in with their existing passwords. The firebase-to-supabase auth middleware for verifying Firebase passwords on first login is labeled work in progress in its README, and its step to update the password in Supabase is still marked to be done, so treat password continuity as an open test rather than a given. Where it does not work, plan a forced reset or a password recovery flow. Rewrite the client SDK calls against the Supabase client and run the app against the pilot database. The output is a test log covering sign-in, sign-up, password reset, social providers and each rewritten query, with a list of accepted password-handling options. The step is done when every failed case has an owner and a fix or a user communication plan.

  5. Run a parallel period or read-only window

    Choose between two approaches and record the choice. A read-only window freezes writes in Firebase while the final export and import run. Dual writes keep both systems current but require the application to write to both and reconcile conflicts, which adds code and test effort. Run the final export, import and row count reconciliation against a fresh snapshot, and compare sampled documents field by field. Confirm backups exist for both sides, including a Firestore export and the self-hosted Supabase database, before the window opens. The output is a reconciliation report with zero unexplained differences and a rollback procedure that names who can invoke it. The step is done when the report is signed off by the engineering lead.

  6. Cut over clients and authentication

    Switch production traffic by releasing the application build that points to the self-hosted Supabase URL and keys, and update the Storage references and any custom domains that serve files. Verify that tokens issued by the new Auth service are accepted by PostgREST and Storage policies, and that the Studio dashboard is protected with its password. Watch error rates, sign-in success and query latency during the first hours against an agreed threshold. The output is a signed-off cutover checklist that lists each switched component, the verification run, the person who approved it, and the rollback trigger. The step is done when the checklist is complete and the Firebase project has been set to read-only for application traffic.

  7. Decommission Firebase after a retention period

    Once production has run on Supabase for a period the business agrees in writing, export a final archive of Firestore, Auth and Storage data to storage you control, then remove client keys and disable the Firebase services in use. Confirm the Firebase billing plan changes or the project is shut down, and revoke service account keys used by migration scripts. Record which Firebase features are no longer needed, such as Cloud Functions or Hosting, and close them as separate work. The output is a decommission record listing archived artifacts, revoked credentials and the date each Firebase service was disabled. The step is done when the record is filed with the security owner.

Running Firebase and Supabase in parallel without losing writes

A parallel run only works if you decide, for each phase, which system is the write source. While Firebase remains the source, every write that lands in Supabase is a copy that can drift. Name the owner of each collection and table in writing, and set the date when writes move. Until that switch, client apps keep writing to Firebase, and the Supabase copy is refreshed from a known export. After the switch, Firebase becomes read-only for migrated data, so a stale client build cannot create records the new side never sees. Test that freeze with an old app build before you rely on it.

Location is the constraint that differs most between the two systems. A Cloud Firestore database's location cannot be changed after it is provisioned, and Firebase Authentication processes data only in the United States, so the location you chose at setup largely decides where your data sits. A self-hosted Supabase stack runs in infrastructure you pick, so you can place the database, Auth and Storage in the same region you need. Confirm with your compliance owner which regions and data classes apply before the first load, because moving a self-hosted stack later is a separate project. Record the region of each component in your cutover runbook.

Verify each load before anyone trusts it. Compare row counts per collection against the Firestore export, then sample documents across the collection (including the oldest, the newest and records with nested data that the custom hooks split into related tables) and check field values field by field. Keep the comparison scripts and their output as evidence for your change record. Password hashes need their own test. Migrated users must sign in on Supabase with their existing passwords, and that path depends on the Firebase scrypt parameters being saved and the verification middleware working in your environment. The firebase-to-supabase auth tooling marks this middleware as work in progress, so run a first-login test with a set of test accounts and confirm how the password update step behaves before you move real users.

How the migration differs by app size and starting point

A small app with a few collections, one or two client platforms and no enterprise single sign-on usually has the shortest path. The Firestore export is simple to flatten into Postgres tables, and the Auth import is limited to a modest user base. The effort is concentrated in rewriting client SDK calls and confirming that the password hashes import correctly, so most of the work sits in the application code rather than the data.

  • Data shape: Few collections flatten into one table each, and the scripts documented in the firebase-to-supabase repository can often handle them with light key renaming.
  • Client SDK rewrite: Each Firestore read, write and listener becomes a Supabase client call, which is usually the largest effort item even for a small app.
  • Password hashes: Confirm with a test user that the scrypt parameters saved from the Firebase console allow sign-in without a reset, because the middleware for verifying existing Firebase passwords is still marked work in progress.
  • Storage: Remember that a missing target bucket is created as non-public, so set access permissions after copying files.
  • Operations: A single node is enough to start, but you will still own backups, updates and patching.

Before cutover, confirm that your app does not depend on any hosted-only feature listed in the self-hosting docs, and ask Supabase or your implementation partner to confirm which of those features your app touches.

What drives the cost and duration of the move

This table breaks the move into cost components, showing who is paid, whether each cost is one-time or recurring, and what pushes it up. Use it to structure a quote request and to see which inputs your own Firebase project will change the most.

Cost componentWho is paid or who bears itOne-time or recurringWhat drives it up
Schema design and data model mappingInternal engineers, or a partner under a written fixed scopeOne-timeNumber of Firestore collections, nested data depth, and how many subcollections must become related tables
Client SDK and security rewriteInternal app teams, or a partner under a written fixed scopeOne-timeNumber of client apps, use of Firestore listeners, and security rules that must be rebuilt as Postgres row level security policies
Migration scripting and test runsInternal engineers or a partner; scripts come from the supabase-community firebase-to-supabase repositoryOne-timeCustom hooks for renaming keys, calculating fields or splitting nested data; repeated test loads before cutover
Auth migration and password testingInternal engineers or a partnerOne-timeNumber of sign-in providers, reliance on modified scrypt hash verification, and the decision on forced password resets
Storage file transfer and bucket permissionsInternal engineers or a partnerOne-timeFile count and total volume, downloads to local disk, and access policies that must be set after buckets are created as non-public
Server hosting, storage and backupsYour cloud account or data center providerRecurringMinimum requirements are 4 GB RAM, 2 CPU cores and a 40 GB SSD; recommended is 8 GB RAM, 4 cores and 80 GB (Supabase Docker self-hosting guide); growth in data and file volume
Patching, upgrades and monitoringYour platform team or a retained partnerRecurringFrequency of Docker configuration releases, such as 0.8.3, and upstream Auth, PostgREST and Realtime pins that must be pulled and tested

What usually goes wrong in a Firebase to Supabase move

Most failed or delayed Firebase to Supabase moves hit the same few points: credentials, access control, data shape, files and operations. Each card below names one risk, why it matters for this migration, and the check to run before cutover.

Password hashes that do not verify

Firebase Auth stores passwords as a modified scrypt hash. Supabase's import inserts users into auth.users only after you save the Firebase project's scrypt parameters from the Firebase console, so a missing or wrong parameter leaves every imported user unable to sign in. The firebase-to-supabase middleware for verifying old passwords on first login is still marked work in progress, and the step that rewrites the password in Supabase is still open. Test a few exported accounts end to end before you plan around keeping existing passwords, and budget for password resets if they fail.

Security rules that do not map to RLS

Firebase security rules run as a separate policy language evaluated per request, while Supabase relies on Postgres row level security policies attached to each table. A rule that filtered by user ID in Firestore has no automatic equivalent, and a table left with RLS disabled is readable through the public API. Map every collection's read and write rules to a policy before import, then test each policy as an anonymous user, a signed-in user and another user's session. Never expose a table without RLS enabled.

Flattened data that loses structure

The Firestore migration flattens each collection into one Postgres table with text, numeric, boolean or jsonb columns. Nested maps and arrays often arrive as jsonb blobs, and references between documents become plain strings unless you split them into related tables. The migration offers custom hooks that rename keys, calculate values and split nested data. Decide the target schema for each collection with the application team, write the hooks in advance, and check row counts and sample documents against the source.

Storage left non-public after import

The Storage migration downloads files from the Firebase bucket to local disk and uploads them with upload.js. When the target bucket does not exist, the script creates it as non-public, so files that were publicly readable in Firebase become inaccessible to the app. Access policies on the bucket must then be rebuilt by hand. Compare the public or private setting of each source bucket with its Supabase counterpart, and confirm a signed-in user can read only the objects they should.

Self-hosting without managed backups

Self-hosted Supabase does not include managed backups or point-in-time recovery, and the Supabase changelog flags some Storage database migrations as one-way that require a database backup before updating. Your team must schedule Postgres backups, test restores into a separate environment and keep the Docker configuration version recorded. Before any upgrade, take a backup, confirm it restores, and then pull the new release. Ask who owns each step and how the restore is tested.

Common questions before moving from Firebase to Supabase

How long does a Firebase to Supabase migration take?

The duration depends mostly on data volume, how many Firestore collections need reshaping into tables, how many Auth users and Storage files must move, and how much client code changes. No supplied source gives a typical timeline, so ask for one tied to your own collection count, user count and file volume in a written scope. The Firestore path is script-driven, but each collection may need custom hooks to rename keys or split nested data into related tables, and that design work usually takes the most time. Plan for a parallel run and a cutover window, and confirm both with your team and any implementation partner before work starts.

What does a Firebase to Supabase migration cost?

Costs fall into a few components: the Supabase software itself (Apache-2.0, no license fee), the servers, storage and backups you run, the data reshaping and client SDK rewrite, and the people who operate and patch the stack. Supabase's pricing page covers its hosted plans, which are a separate option if you do not want to self-host. Migration tooling is open source, so the main one-time costs are engineering and testing time. Recurring costs are infrastructure and ongoing operations. Ask any vendor or partner for a quote that separates one-time migration work from recurring hosting and support, and state which Firebase bills you expect to stop.

Can our own team run this migration without outside help?

A team with Postgres, Node.js and Firebase experience can run the supplied scripts, but the work has more decisions than the scripts make. Those decisions include Postgres table design, primary key strategy (uuid, bigserial or firestore_id), row level security policies replacing Firebase security rules, and client SDK changes. Supabase's self-hosting docs describe the platform as community-supported, so no vendor support contract comes with it. Outside help can be scoped in writing for specific parts, such as the data model, the auth cutover or a pre-production test run, while your team keeps ownership of the result.

Do Firebase password hashes move to Supabase without forcing resets?

Not automatically in a way you can rely on without testing. Firebase Auth uses a modified scrypt by default, and Supabase's documented path exports users with firestoreusers2json.js, saves the Firebase project's scrypt hash parameters from the Firebase console, and inserts users into auth.users with import_users.js. However, the firebase-to-supabase auth README labels the middleware that verifies existing Firebase passwords on first login as work in progress, and the step that updates the password in Supabase is still marked to be done for every hosting option. Plan either a password reset flow or a tested custom verification step, and confirm the current state of that repository before you commit.

What does self-hosting Supabase require for operations and support?

Your team owns patching, backups, monitoring and upgrades. Supabase's Docker guide lists minimum requirements of 4 GB RAM, 2 CPU cores and a 40 GB SSD, and recommends 8 GB RAM, 4 cores and 80 GB. The Compose stack includes Studio, Envoy, Auth, PostgREST, Realtime, Storage, Postgres, Supavisor and Edge Runtime, and each configuration release pins specific upstream versions you must pull and recreate. Some hosted features are unavailable when self-hosting, including branching, managed backups, point-in-time recovery and the Management API. Self-hosted Supabase is community-supported through GitHub, Discord and Reddit, and enterprises are directed to contact Supabase's Growth Team for other options.

Does Supabase's Apache-2.0 license change our commercial terms?

The Apache-2.0 license permits commercial use, modification and redistribution of the Supabase repository, so you do not pay a license fee to run the self-hosted stack. It does not change the terms of any Supabase Cloud subscription you already hold, which are set by Supabase's own agreements. Confirm with your legal team how Apache-2.0 notices and attribution apply to your deployment, and check the license on any third-party components or community tools you add. Licensing is one input; the larger commercial difference is who carries operations, security patching and support.

What should we check in the self-hosted Docker releases before upgrading?

Read each release note before pulling a new configuration. The self-hosted Docker configuration reached 0.8.3 on October 16, 2026, and its changelog flags security fixes for Storage and Realtime as well as one-way Storage database migrations that require a database backup before updating. Test upgrades in a staging copy first, and schedule them as part of routine operations. Ask whether your planned version carries those fixes and whether any migration is irreversible.

How DeployOpen works on this

DeployOpen plans, implements, integrates, hardens, documents and supports self-hosted Supabase inside your own cloud accounts, data centers or air-gapped networks. For a Firebase move, we start from a written scope that separates the Firestore data, Auth users and Storage files, so each one is tested before cutover.

How we scope

  • Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts
  • The written scope lists each Firestore collection, the Auth user set and each Storage bucket to be moved
  • We record which Firebase features are out of scope, such as Realtime Database, Cloud Functions and OAuth sessions
  • Ongoing support, upgrades and continuous testing are available as a retainer after cutover

How we build

  • Collections are flattened into Postgres tables, with key strategy and custom hooks agreed per collection
  • Auth users are imported with the Firebase project's scrypt parameters, and password behavior is tested before cutover
  • Storage files are moved to Supabase buckets, with bucket visibility and access policies rebuilt and reviewed
  • Self-hosted services are configured with generated secrets, protected Studio access and removed services not in use

How we hand over

  • Deliverables include the data mapping, migration runbook, rollback steps and a record of reconciliation checks
  • Row level security policies and access rules are documented alongside the tables they protect
  • Operators are trained on backups, Docker Compose updates and the changelog steps that require a database backup first
  • Evidence for compliance assessments is organized for your independent auditors, who issue any reports

How we support

  • Support after handover can be provided under a retainer covering upgrades and patching of the Docker configuration
  • We help you check each new release against your own environment and test changes in a staging copy first
  • Security testing of the application, APIs and cloud configuration can be scoped as a separate engagement
  • Questions on vendor support paths, such as community channels or an enterprise contract, are confirmed with the vendor

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.