Self-Host FerretDB: MongoDB's API on PostgreSQL

Self-Host FerretDB: MongoDB's API on PostgreSQL

A while back I watched a team ship a perfectly good prototype on MongoDB, then stall for a week when legal asked one question: what license is the database under? The answer, since 2018, is the SSPL, which is not an OSI-approved open-source license. For a product that wanted to sell an on-prem, self-hostable version, that was a real problem. They loved the document model. They just could not ship the engine.

FerretDB is the tool that would have saved them the week. It is an open-source database that speaks MongoDB's wire protocol, so your app and your mongosh shell think they are talking to MongoDB, while underneath it stores everything in PostgreSQL. Apache 2.0 license, your data on Postgres, the same document API you already write against.

How it actually works

FerretDB is a proxy, not a fork. There are three layers: your application talks to FerretDB on the standard MongoDB port 27017, FerretDB translates those MongoDB 5.0+ wire-protocol commands into SQL, and PostgreSQL does the real storage and query work. Any MongoDB driver connects to it unchanged, because as far as the driver knows, it is MongoDB.

The interesting change is in version 2. FerretDB 2.x stores documents using the DocumentDB PostgreSQL extension, the same BSON storage and indexing engine Microsoft open-sourced in 2025. That is a big deal: the old 1.x line kept documents in JSONB and paid for it on complex queries, while 2.x pushes the document work down into a purpose-built extension and gets dramatically closer to native performance. So it is not "MongoDB emulated in a JSON column" anymore. It is a document engine running inside Postgres, with FerretDB as the translator on top.

You keep your tools

This is the part that makes it easy to try. Point mongosh at your FerretDB instance with a normal connection string:

mongosh "mongodb://user:password@your-ferretdb.elestio.app:27017/app"

Then run the exact Mongo commands you already know:

db.movies.insertOne({ title: "Heat", year: 1995, genres: ["crime", "drama"] })
db.movies.find({ genres: "crime" })

Application code does not change either. The official MongoDB driver connects the same way it always has:

import { MongoClient } from "mongodb";

const client = new MongoClient(
  "mongodb://user:password@your-ferretdb.elestio.app:27017/"
);
await client.connect();

const db = client.db("app");
await db.collection("movies").insertOne({ title: "Heat", year: 1995 });

No new query language, no ORM swap, no rewrite. That is the whole pitch.

The honest part

FerretDB is a drop-in replacement for MongoDB 5.0+ in many cases, not all of them. It targets the standard CRUD and aggregation surface that most applications actually use, and it is upfront about the gaps: the project maintains published lists of supported commands and known differences. If your app leans on exotic operators, change streams in anger, or Atlas-specific managed features, check those lists before you commit. If you are doing normal document reads, writes, and aggregations, you will mostly forget FerretDB is there.

So who is this for? Three groups. Teams that need a genuinely open-source document database because SSPL is a non-starter for their distribution model. Teams already fluent in PostgreSQL who would rather back up, monitor, and tune one database engine than two. And anyone who wants the MongoDB developer experience without betting their data layer on a single vendor's licensing decisions.

Dimension MongoDB FerretDB
License SSPL (not OSI open source) Apache 2.0
Storage engine WiredTiger PostgreSQL plus DocumentDB extension
Drivers and shell MongoDB drivers, mongosh The same MongoDB drivers, mongosh
Ops surface A separate database to run Reuses your Postgres backups and skills
Best when You need every feature or Atlas services You want the document API without SSPL

Running it on Elestio

FerretDB needs a PostgreSQL that has the DocumentDB extension installed, which is the one piece of setup people trip on. The quickstart eval image bundles everything, but the project is clear that it is for testing, not production. On Elestio you skip that: managed FerretDB with the right Postgres backend, SSL, automated backups, and updates starts at $11/month. Deploy it from the FerretDB service page and point your existing Mongo connection string at it.

Troubleshooting

  • mongosh cannot connect: check whether TLS is expected. If your instance terminates TLS, add tls=true to the URI; if it does not, make sure your client is not forcing it. A mismatch here is the most common first error.
  • A command returns "not implemented": you have hit one of the known differences. Look it up in FerretDB's supported-commands list and, usually, there is a close equivalent.
  • Queries are slower than expected: confirm you are actually on a Postgres with the DocumentDB extension, not a plain Postgres. Without the extension you lose the v2 performance path.
  • Authentication fails: FerretDB delegates auth to the underlying Postgres roles, so the username and password in your Mongo URI are Postgres credentials. Verify them against the database, not an old Atlas user.

MongoDB's document model is genuinely nice to build on. FerretDB lets you keep it while standing on an engine you can read the source of, back up like any Postgres, and never get a surprise licensing email about. For a lot of teams, that trade is an easy yes.

Thanks for reading ❤️ See you in the next one 👋