Using PostgreSQL as a MongoDB drop-in replacement with FerretDB

Page contents

Many companies stay stuck with MongoDB because moving to a different database is too complex and risky, but there is a better way. Use FerretDB to mimick a MongoDB for your applications, but with reliable PostgreSQL storage.

Switching away from MongoDB

MongoDB has seen an impressive number of issues over the years, from severe data integrity problems, sharding issues at scale to vulnerabilities like mongobleed, which allowed unauthenticated attackers to freely read memory contents.


Companies using MongoDB have issues transitioning to a new database, since the database clients are not standardized for use with other databases, so switching databases requires application rewrites on top of data migration.

This is where FerretDB comes into the picture: it works as a proxy to translate MongoDB queries into PostgreSQL equivalents, effectively allowing applications to use PostgreSQL as a drop-in replacement without changing a single line of code.

How FerretDB works

Even though it has "DB" in the name, FerretDB is actually not a database. It is a translation layer, a proxy if you will. It translates MongoDB wire protocol from clients into PostgreSQL queries, and the result back into MongoDB-compatible format.

It uses the DocumentDB postgres extension, heavily improving query speeds by building native BSON support into PostgreSQL itself.

For larger scale deployments, it can instead use the PostgreSQL-compatible YugabyteDB as a storage backend, without any changes to application logic.

Setup

FerretDB is best deployed in a docker container, tightly bundling the entire lifecycle into one place. You can try it out yourself by creating a compose.yml file for a local test deployment:

services:
  postgres:
    image: ghcr.io/ferretdb/postgres-documentdb:17-0.107.0-ferretdb-2.7.0
    restart: on-failure
    environment:
      - POSTGRES_USER=username
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=postgres
    volumes:
      - ./data:/var/lib/postgresql/data

  ferretdb:
    image: ghcr.io/ferretdb/ferretdb:2.7.0
    restart: on-failure
    ports:
      - 27017:27017
    environment:
      - FERRETDB_POSTGRESQL_URL=postgres://username:password@postgres:5432/postgres

networks:
  default:
    name: ferretdb

Then start it

docker compose up -d

You can now connect to your FerretDB interface at mongodb://username:password@127.0.0.1.

MongoDB ecosystem tools like mongosh or the Atlas GUI are fully supported as well.

If you don't have mongosh installed, you can start up a temporary container to explore the database:

docker run --rm -it --network=ferretdb --entrypoint=mongosh \
  mongo mongodb://username:password@ferretdb/

Test your application against the ferretdb instance before deciding to migrate. FerretDB supports virtually all features needed by applications, but did not implement all administrative and management portions yet. Check the compatibility documentation to see if something you require is missing before migration.

A note about production hosting

Hosting FerretDB in production largely means maintaining a reliable PostgreSQL cluster, with backups, monitoring and failover. This part will be wildly different from your previous MongoDB instance, since managing clusters for PostgreSQL and MongoDB are nothing alike.


If you are worried about hosting PostgreSQL in production, the open source community has you covered with pigsty for bare-metal or stackgres for kubernetes deployments. They automate every step of the process, including scaling, high-availability, backups and retention, automatic failover, self-healing, monitoring, and of course a nice web UI to manage and maintain it all in one click. All you have to do is install the DocumentDB postgres extension and they will do the rest.

For extremely large scale deployments, picking YugabyteDB will help you scale horizontally, with multi-master clusters and better node resource usage.

Migrating data from MongoDB to FerretDB

Since FerretDB fully emulates the MongoDB wire protocol, you can use standard MongoDB tools to backup the MongoDB data and restore it onto FerretDB.

Just take a binary dump of the entire database contents:

mongodump --uri="mongodb://user:pass@old_mongodb_host/"

Then restore it onto FerretDB:

mongorestore --uri "mongodb://user:pass@new_ferretdb_host/"

And your FerretDB instance is ready to go! No hidden switches or caveats, simply use the tools you are already familiar with. You aren't locked into MongoDB nearly as much as internet chatter would have you believe.

More articles

Understanding hyperconverged infrastructure

...and how it compares to real cloud stacks

Understanding hashmap fundamentals

If not array - why array shaped?

Practical wget use cases

From downloads to web automation