Building My Own Firebase Alternative (flexdocs) — Self-Hosting a Realtime BaaS with Docker, Nginx & MongoDB

Building My Own Firebase Alternative (flexdocs) — Self-Hosting a Realtime BaaS with Docker, Nginx & MongoDB

I built my own self-hosted Firebase alternative to escape Firebase pricing and lock-in. Meet flexdocs — a realtime BaaS on Docker, Nginx & MongoDB.

Building My Own Firebase Alternative (flexdocs) — Self-Hosting a Realtime BaaS with Docker, Nginx & MongoDB

My Firebase bill didn't ruin me. The fear of it did.

I had a small app with maybe a few hundred users. Nothing wild. But every time it got a little traffic bump, I'd open the Firebase console and hold my breath. Reads, writes, function calls — all of it ticking up on a meter I didn't really control. That's the moment I decided to build my own self-hosted Firebase alternative. I call it flexdocs.

This post is the honest story of why I did it, what's inside it, and whether you should even bother doing the same. Spoiler: probably not. But if you're the kind of person who likes owning your stack, stick around.

Tip

TL;DR — flexdocs is a self-hosted, realtime BaaS I built to escape Firebase pricing and vendor lock-in. It runs four Docker containers — Nginx, a Node API with WebSockets, a Next.js admin, and MongoDB — behind one reverse proxy. You get auth, a document database, file storage, and realtime sockets on a $5 server you actually control.

Why I Wanted Off Firebase in the First Place

Two words: vendor lock-in.

Firestore's data model and query language are proprietary. The deeper you build into it, the harder it is to leave. Your whole app starts to think in Firebase. And the pricing is tied right to that — the Blaze plan charges per operation, so cost grows with every read and write.

I'm not the only one who felt this. Teams routinely report Firebase bills jumping from around $50 a month to thousands after a launch goes well (Indie Hackers, Sashido). Success shouldn't feel like a bill you can't predict.

So I gave myself three rules: no per-operation pricing, no lock-in, and I host it myself.

What a Self-Hosted Firebase Alternative Actually Needs

Before writing a line of code, I made a short list. To replace Firebase for my needs, the backend had to do four things:

  • Auth — sign up, log in, tokens.
  • A document database — store and query JSON, Firestore-style.
  • File storage — upload images and files, get back a URL.
  • Realtime — push changes to clients the instant they happen.

That's the core of any backend-as-a-service. There are great open-source options that cover this already — Supabase, Appwrite, and PocketBase are the big names in 2026 (Encore, NocoBase). I looked hard at all three.

Supabase is Postgres with a whole stack of services on top. Appwrite runs on MariaDB with a document-style API. PocketBase is a single Go binary with SQLite — genuinely lovely for small stuff (Elest.io).

So why build my own? Two reasons. I wanted to actually understand every piece. And I wanted a document database that felt like Firestore, on infrastructure I already knew. That pushed me toward MongoDB.

Meet flexdocs: A Realtime BaaS on Docker, Nginx & MongoDB

flexdocs is four Docker containers, wired up with Docker Compose. That's the whole thing.

Here's the layout:

# docker-compose.yml (simplified)
services:
  nginx:      # reverse proxy — the only thing exposed
    image: nginx:alpine
    ports: ["80:80"]
  api:        # Node + Express + socket.io + sharp
    build: ./api
  web:        # Next.js admin dashboard
    build: ./web
  mongodb:    # the database
    image: mongo:6.0

Each container has one job:

  • Nginx is the front door. It's the only container that talks to the outside world.
  • api is a Node/Express server. It handles auth, database queries, file uploads (resized with sharp), and the realtime WebSocket connections via socket.io.
  • web is a small Next.js admin dashboard so I can click around my data instead of writing scripts.
  • mongodb stores everything. Files live on disk, mounted into the API container.

One command brings the whole thing up. docker compose up -d. That still makes me smile.

Why MongoDB and Not Postgres

This is where people will argue with me, and that's fair.

Postgres is the "correct" answer for a lot of apps. But I was coming from Firestore, where you store documents, not rows. MongoDB kept that mental model intact. My data is JSON going in and JSON coming out. No object-relational translation in my head.

Is it the right pick for everyone? No. If you need real relational power and joins, Postgres wins, full stop (Northflank). But for a Firebase-style document store that I self-host, Mongo felt like home. And Mongo 6 on a small box barely breaks a sweat.

Nginx: The Reverse Proxy That Ties It Together

Here's a thing I didn't appreciate until I built this: the reverse proxy does a lot of quiet, heavy lifting.

Nginx sits in front of both the API and the admin dashboard. One hostname, one entry point. It routes /api to the Node server and everything else to the Next.js app. It also handles the tricky part of realtime — upgrading an HTTP connection to a WebSocket.

That upgrade needs two specific headers, and if you forget them, your sockets silently die:

# nginx.conf — the bit that makes WebSockets work
location /socket.io/ {
    proxy_pass http://api:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

I lost an evening to those four lines once. Now they're the first thing I check.

Warning

If your realtime updates work locally but break in production, check your reverse proxy first. Nine times out of ten it's the missing Upgrade and Connection headers.

The Realtime Part (a.k.a. the Fun Part)

Realtime is the whole reason a BaaS feels magic. You change data in one place and every connected client just knows.

In flexdocs, the API keeps a socket.io connection open to each client. When a document changes, the server pushes the update down that socket. No polling. No refresh button. The client subscribes to a collection and gets changes as they land — the same feeling you get from Firestore's listeners.

This is the part I'm proudest of, honestly. Watching two browser tabs update in lockstep the first time felt like a small miracle.

Should You Build One Too? (Honestly, Probably Not)

Let me be real with you.

Self-hosting means you own the boring parts now. Updates, backups, monitoring, security patches — all yours (Encore). Firebase did that so I didn't have to. Building flexdocs traded a scary bill for a pile of responsibility.

So here's my honest take:

  • Just want to ship? Use Supabase, Appwrite, or PocketBase. They're excellent and you'll move faster.
  • Want to learn how a backend really works, and own every layer? Build one. You'll understand Firebase better after you've replaced it.

For me it was worth it. My "bill" is now a small VPS that costs a few dollars a month, and it doesn't move when my traffic does. That peace of mind is the feature I actually wanted the whole time.

Wrapping Up

flexdocs isn't going to dethrone anyone. It's a self-hosted Firebase alternative that does exactly what I need — auth, documents, files, and realtime — on Docker, Nginx, and MongoDB I fully control.

The bigger lesson? You don't have to accept a backend you can't see inside of. Whether you build your own or pick an open-source one, owning your stack is more doable in 2026 than it's ever been.

Next up, I want to write about hardening this thing for production — TLS, backups, and not getting paged at 2 a.m. If that sounds useful, tell me in the comments and I'll bump it up the list.

Got questions about the setup, or running your own? Drop a comment or share this with the friend who keeps complaining about their Firebase bill.

Related Posts


Sources: Encore — Firebase Alternatives 2026, Northflank — Supabase Alternatives, Elest.io — Supabase vs Appwrite vs PocketBase, NocoBase — Open-Source Firebase Alternatives, Indie Hackers — Firebase Alternatives That Work in 2026, Sashido — Firebase Pricing Traps 2026.