scribase
Migrate from Firebase

Firestore to Postgres, with every password still working.

Bring the app to a Postgres backend you can query, branch, and export. Scribase imports Firestore, Firebase Auth including scrypt password hashes, and Cloud Storage, then shows a table-by-table verification report.

Four steps in the console: connect the source, review a dry run that writes nothing, run it, and read the verification report. Your place is saved if you close the tab; credentials never are.

What moves

Everything a Firebase app runs on

Firestore
Each collection group becomes a Postgres table with path, id, parent_path, and a jsonb data column. Subcollections become parent__child tables.
Typed values
Timestamps, references, geo points, bytes, maps, and arrays convert to plain JSON you can index and query with SQL.
Firebase Auth
Every user with email, phone, verification state, custom claims, and linked Google, Apple, GitHub, Facebook, Microsoft, and Twitter identities.
Passwords
Firebase modified-scrypt hashes, carried with your project hash parameters and verified natively at sign-in.
Cloud Storage
Every bucket and object, copied into private buckets with a SHA-256 check on each file.

What stays the same

  • Passwords: users sign in with the password they already have
  • Old Firebase UIDs, mapped to new ids in public.firebase_auth_uid_map so app data that stored UIDs still joins
  • Document ids and paths, so references between documents still resolve
  • Disabled users stay disabled

What you do by hand

  • Firestore and Storage security rules are not SQL. Every imported table starts with row level security on and no policies, so nothing is exposed until you write policies.
  • Cloud Functions are not part of an export. Port them to Scribase functions (Deno).
  • Multi-factor enrollments cannot be exported from Firebase; affected users re-enroll.
How it works

Plan, run, prove

  1. Step 1

    Export Firestore and Storage

    The scribase package reads Firestore and Cloud Storage through Google REST APIs with a service account. No Firebase SDK needed.

    import { writeFirebaseExport } from 'scribase/importers';
    
    await writeFirebaseExport({
      projectId: 'my-app',
      serviceAccount: JSON.parse(process.env.GOOGLE_SERVICE_ACCOUNT!),
      directory: './firebase-my-app',
      authExportPath: './auth.json',
      buckets: ['my-app.appspot.com'],
    });
  2. Step 2

    Export Auth with the Firebase CLI

    Password hashes are only available through the Firebase CLI. Copy the hash parameters from Authentication, Users, Password hash parameters.

    firebase auth:export auth.json --format=JSON --project my-app
  3. Step 3

    Plan, then run

    Upload small exports in the console wizard, or place the folder in the server exports directory. The dry run shows every collection, user, and file first.

    await scribase.imports.createFrom({
      source: 'firebase',
      sourceFirebaseProjectId: 'my-app',
      sourceExportDir: 'firebase-my-app',
      sourceHashConfig: { base64_signer_key: '…', base64_salt_separator: 'Bw==', rounds: 8, mem_cost: 14 },
      destination: { organizationId: 'acme', projectId: 'app', environmentId: 'production' },
      verifyLogin: { email: 'you@yourapp.com', password: process.env.TEST_PASSWORD },
    });
  4. Step 4

    Read the report

    Row counts and checksums per table, auth user and object counts, and a sign-in proof that recomputes your test account against the migrated scrypt hash.

The verification report

Old versus new, table by table

Every import ends with this. The verdict is VERIFIED only when every row count and checksum matches, every policy is present, and the sign-in proof passes. The numbers below are an example of the format.

TableFirebase rowsScribase rowsChecksum
public.profiles12,40812,408 match
public.orders88,21488,214 match
public.order_items240,977240,977 match
Also checked: RLS policy parity, auth user count, storage object count, and a sign-in with an account you control. Verdict: VERIFIED
Hosted migration

Want us to host it? Join the Firebase waitlist.

The importer runs today on any Scribase you operate. Hosted Scribase opens by source, in waitlist order. Tell us your size and we will reach out when your slot opens.

FAQ

Migrating from Firebase

How can passwords survive the move?

Firebase hashes passwords with a modified scrypt keyed by your project signer key. Scribase stores each hash together with those parameters and verifies them at sign-in the same way Firebase does, so no user needs a reset.

Will my data still be documents?

Each document lands as a row with its fields in a jsonb column, so you can query it with SQL right away (data->>'email') and move hot fields into real columns later with ordinary migrations.

Do I need to keep paying Google during the move?

Only for the export itself. Reading documents and objects counts toward your normal Firestore and Storage usage for one pass.