Fireloom / Compare

Firestore to Postgres: the options, compared.

There are four common ways to get Firebase data into PostgreSQL. Each one makes sense somewhere. Here's how they differ on latency, deletes, subcollections, Firestore reads and upkeep.

Comparison of ways to sync Firestore to PostgreSQL
Export + import scriptCloud Functions triggersBatch ETL toolFireloom
FreshnessWhenever you re-run itSecondsEach scheduled runSeconds
DeletesOnly if you rebuild the tableIf you handle themOften needs a full refreshStreamed, and checked daily
Subcollections at any depthYes (exports include them)One trigger per path patternVaries by toolYes, one table, parent links
Existing data (backfill)YesSeparate scriptYesYes, from an export or directly
Firestore reads after the first copyEvery document, every exportNone for the trigger itselfOften every document, every runOnly changed documents
Restarts and outagesn/aRetries you configure; events can arrive out of orderNext runResumes from checkpoints
Code to write and runConverter and loaderFunctions, schema, deploysConfig; often a self-hosted toolNone
Access to your FirestoreYoursRuns in your projectUsually a read keyRead-only key, plus export-only role

Export and import

gcloud firestore export writes LevelDB files to Cloud Storage. To use them in Postgres you need a converter and a loader. It's a reasonable choice for a one-time copy, such as a migration rehearsal. As a sync it's expensive: every export reads every document, and the result is stale the moment it finishes.

Cloud Functions triggers

An onDocumentWritten trigger can write each change to Postgres within seconds. You own the code: the schema, connection pooling from functions, a backfill for existing data, delete handling, retries, and ordering (events can be delivered more than once and out of order, so writes need versions). Nested subcollections need their own trigger paths. It works well for teams that want full control and have time to maintain it.

Batch ETL tools

General-purpose ELT tools move data on a schedule. Firestore has no change cursor, so many connectors re-read whole collections on each run, which costs one read per document every time. Check how your tool handles deletes and subcollections before relying on it.

Fireloom

Fireloom listens to Firestore's change stream and keeps one Postgres table current within seconds, deletes and subcollections included. The first load reads each document once (or uses an export), restarts resume from checkpoints, and a daily count check catches drift. You connect two databases; there's nothing to deploy. Inside the sync engine covers the details.

When it's not the right fit: if you need Postgres-to-Firestore writes, typed columns per field today, or a destination other than Postgres, Fireloom doesn't do that yet.

Try it free

Up to 100,000 documents per Firebase project, real-time streaming included.

Start syncing free