Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

firebase-alternative-free

MongoDB Python scope License

A database is not a Firebase replacement. That sentence is the reason this repository exists, and it belongs at the top rather than buried in a caveats section at the bottom.

Firebase is a bundle: Firestore or Realtime Database for storage, Authentication, client SDKs that keep a local cache in sync over a live connection, Hosting, Cloud Functions, Cloud Messaging, Analytics, Crashlytics. Search results for "free Firebase alternative" mostly return databases. A database replaces one item on that list. Everything else is work you would be picking up.

What follows is a decision aid first and a migration toolkit second. If you read only one section, read the one arguing you should stay.


First question: which part of Firebase are you actually leaving?

Firebase piece What it does for you What a plain database gives you instead
Firestore / RTDB Document storage Document storage. This is the one that maps.
Realtime listeners (onSnapshot) Server pushes changes to every connected client Nothing. You build it.
Offline persistence Local cache, queued writes, automatic replay on reconnect Nothing. You build it.
Security Rules Per-document authorisation enforced server-side, so clients can talk to the database directly Nothing. You put an API in front and authorise there.
Authentication Identity, providers, sessions, token refresh Nothing. Separate concern, separate product.
Hosting / Functions Static hosting, serverless compute Nothing. Separate concern.
Analytics / Crashlytics Product and crash telemetry Nothing. Separate concern.

Last verified: 2026-08-18. Product surfaces change — check firebase.google.com/docs rather than trusting this table indefinitely.

If your honest answer is "I only use Firestore as a database, my server talks to it, my clients talk to my server" — then row one is your whole migration and the scripts here will do most of it.

If your answer involves onSnapshot in a mobile app with a spotty connection, keep reading, but adjust your estimate upward by a lot.


The honest answer for a lot of you: do not do this

Reasons to stay on Firebase, stated as specifically as I can manage:

  • Your clients talk to Firestore directly. Firebase's model is that the browser or phone holds a credential and Security Rules decide what it may read and write. Take Firestore out and you need a server between the client and the data, with authentication, authorisation, input validation and rate limiting — because the alternative is a database with an open port and no rules engine. That server is weeks of work and a permanent maintenance obligation. It is not one afternoon.
  • You rely on offline mode. The Firestore SDK caches locally, serves reads from the cache when the network is gone, queues writes, and replays them on reconnect. Reimplementing that correctly means conflict resolution, and conflict resolution is a research problem with a long history of subtly wrong implementations. Mobile apps in particular should think very hard here.
  • The free tier is working for you. Firebase's Spark plan has real free quotas and a lot of projects never leave them. A migration to escape a bill you are not receiving is pure cost.
  • You use Firebase Auth. It is genuinely good, it is not the database, and it does not have to move just because the data does. If you migrate the data and keep Auth, you now operate two systems and a token-verification path between them. That is sometimes right and it is never free.
  • Someone told you Firestore "does not scale" or "locks you in." Both claims are overstated. Firestore scales further than most applications ever need, and your data comes out — the scripts here are proof, and they use Google's own documented Admin SDK to do it. Lock-in in Firebase is about the client SDK behaviour, not the data.
  • You are pre-launch. Migrating infrastructure before you have users is the most reliable way to not have users.

The strongest reasons to actually move: you want SQL-shaped or aggregation-heavy queries that Firestore does not do well, you want a database you can point existing tooling at, you have a self-hosting or data-residency requirement, or your architecture is already server-mediated and Firestore is doing nothing that a document store would not.


Who this repository is for

Someone whose application is already server-mediated — a backend that talks to Firestore with the Admin SDK — and who wants that backend to talk to a plain document store instead. For that reader this is a data migration and the scripts here cover it end to end.

It is also for someone who has not decided yet and wants to see the size of the gap in writing. That is the next section.


The export path

Three scripts, run in order, into whatever MongoDB endpoint MONGODB_URI points at — a free one is enough for a trial run. Full flags and behaviour in examples/README.md.

pip install firebase-admin pymongo
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
export MONGODB_URI='mongodb://HOST:27017/appdb'

python examples/firestore_dump.py    --out ./dump --limit 50   # sample first
python examples/firestore_dump.py    --out ./dump              # then everything
python examples/import_documents.py  --in  ./dump --dry-run
python examples/import_documents.py  --in  ./dump
python examples/verify_import.py     --in  ./dump --sample 25

Why not gcloud firestore export. Google's managed export/import service requires the project to be on the Blaze plan, and it writes a binary format into a Cloud Storage bucket intended to be read back by Firestore or loaded into BigQuery. Neither is helpful if you are on Spark and want documents you can read. firestore_dump.py uses the Admin SDK instead: works on any plan, costs one document read per document, and emits JSONL you can inspect with head.

Subcollections. Firestore subcollections hang off documents. A dump of users contains nothing from users/*/orders unless you go looking, and this is the single most common way a Firestore migration silently loses half the data. The dumper finds them with collection group queries and writes them as users__orders.jsonl.

Types. Timestamps, GeoPoints, DocumentReferences and byte fields are tagged in the JSONL and decoded on import, so a round trip does not flatten your data to strings. Anything the dumper could not classify is written as $raw and reported loudly, because that is exactly the field you need to look at.

Rollback. Nothing in this pipeline writes to Firestore. Undoing the migration is repointing your backend at Firebase. Undoing the import is dropping the collections import_documents.py names in its summary; every write is an upsert keyed on the original document ID, so re-running is safe and never duplicates.


What you lose, in detail

Realtime sync

This is the big one and it deserves more than a bullet.

onSnapshot gives you a persistent connection, server-pushed deltas, automatic reconnection with resumption, and a local cache that stays consistent — across every client, on web and mobile, for free, with about four lines of code.

Replacing it means building, roughly:

  1. A change source. Something that knows a document changed. MongoDB change streams do this, but they require a replica set — check whether your target provides one before designing around it. Otherwise you are polling with a updatedAt cursor, which means picking a poll interval and living with the staleness and the load it implies.
  2. A transport. WebSockets or SSE, plus a server that holds connections. Then: reconnection with backoff, resumption from a last-seen position so a reconnecting client does not miss changes, and heartbeats.
  3. A fan-out layer. One process cannot hold every connection forever. Two processes need a bus between them so a write on one reaches subscribers on the other. Redis pub/sub is the usual answer, which is another service.
  4. Subscription authorisation. Firestore's rules decide what a listener may see. Yours has to as well, on subscribe and on every subsequent push, or you have built a data-leak generator.
  5. Client-side state reconciliation. Applying deltas to local state in order, handling out-of-order and duplicate delivery, and reconciling after a gap.

That is not a weekend. Teams that have done it will tell you it is a quarter and then an ongoing maintenance surface. If your product's value depends on live collaborative state, this alone is a reason to stay on Firebase.

Offline persistence

Firestore's SDK reads from a local cache when offline, queues writes, and replays them on reconnect, resolving against the server's state. Rebuilding it means a client-side store, an outbox, replay ordering, and a conflict policy — last-write-wins is easy to implement and easy to lose data with. Budget for this properly or do not promise offline support.

Security Rules

Rules let untrusted clients hold a database credential safely. Without them the model has to change: clients talk to your API, your API talks to the database, and every rule becomes a check in application code. That is a normal architecture — most of the software in the world works this way — but it is a different one, and porting a large firestore.rules file into middleware is a genuine project with a genuine chance of getting an authorisation check wrong.

Do not skip this by exposing a database connection string to a client. There is no version of that which is acceptable.

Everything else

Auth, Hosting, Functions, Messaging, Analytics, Crashlytics, App Check, Remote Config. None of these are a database's job, and none of them are addressed by anything in this repository. If you use them, they stay where they are or they become separate migrations.


Where the data lands

The scripts write to MongoDB, because Firestore documents map onto MongoDB documents with less distortion than onto anything relational. Any MongoDB 7 endpoint works; MONGODB_URI is the only knob.

freebase.cloud is one option for it — MongoDB 7.0.4 over the real wire protocol on port 27017, so mongosh, Mongoose, PyMongo, Motor and the native driver connect unmodified.

mongosh "mongodb://HOST:27017/appdb"
db.users__orders.createIndex({ _parentId: 1, createdAt: -1 })
db.users.find({ "profile.plan": "free" }).limit(5)

Free tier, no credit card, aimed at development, prototyping and small production workloads. No published SLA, uptime figure or backup schedule — and since you are considering leaving a Google-operated service, that difference should weigh heavily rather than being read past.

The MCP angle

The same instance is reachable over MCP, which is a thing Firestore does not offer. In Settings → MCP, mint a token against the connection and take the URL it gives you. With a connection named store you get store_query, store_store, store_list_tables and store_annotate_table.

claude mcp add --transport http store https://freebase.cloud/api/mcp/YOUR_TOKEN

This is genuinely useful during a migration: after import_documents.py runs, you can ask an assistant to look at the imported collections and tell you which fields are inconsistently typed, rather than writing a script per question. Annotate the collections first — store_annotate_table with "users__orders came from Firestore subcollections; _parentId is the user id" saves the model from guessing.

For Claude Desktop, add the URL under Settings → Connectors → Add custom connector; remote HTTP servers are not supported in the desktop config file, and the client-by-client instructions cover the rest. The token sits in the URL path, so treat the whole URL as a secret.


Sources


freebase.cloud is an independent service and is not affiliated with Google LLC, Firebase, MongoDB, Inc., Redis Ltd. or Anthropic, PBC.

About

Free Firebase alternative — when you want a plain database instead of Firestore's lock-in

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors