Getting Started

FerretDB Introduction

Learn FerretDB — the open-source MongoDB-compatible database backed by PostgreSQL, giving you MongoDB's API with full SQL power underneath.

What is FerretDB?

FerretDB is an open-source proxy that translates MongoDB wire protocol messages into SQL queries, running against a PostgreSQL backend. From your application's perspective, it looks and behaves like MongoDB — you use the same drivers, the same query syntax, and the same connection strings. Under the hood, your data is stored in PostgreSQL.

It was created in response to MongoDB's license change in 2018, when MongoDB shifted from the open-source AGPL to the source-available SSPL license. FerretDB offers a truly open-source alternative (Apache 2.0) that maintains MongoDB API compatibility.

Why FerretDB?

The MongoDB Licensing Problem

In 2018, MongoDB changed its license from AGPL to SSPL (Server Side Public License). SSPL requires that if you offer MongoDB as a managed service, you must open-source your entire cloud stack. Major cloud providers (AWS, Google, Azure) rejected this and created their own compatible APIs (DocumentDB, Atlas-compatible services). Many enterprises and open-source projects needed a truly open alternative.

FerretDB addresses this:

  • Apache 2.0 licensed — Truly open-source, no restrictions
  • MongoDB-compatible API — No application code changes needed
  • PostgreSQL backend — Your data lives in a battle-tested, ACID-compliant database

Benefits of PostgreSQL as the Backend

Running FerretDB on PostgreSQL gives you advantages MongoDB alone can't offer:

  • True ACID transactions across documents
  • Full SQL analytics — Run complex analytical queries directly on your data via psql
  • PostgreSQL ecosystem — pgAdmin, Flyway migrations, pg_dump backups, replication
  • Existing infrastructure — If you already run PostgreSQL, no new database to operate
  • JSONB indexing — PostgreSQL's JSONB type is highly optimized for JSON storage and querying

Architecture

text
Your App
  ↓ (MongoDB wire protocol)
FerretDB (proxy)
  ↓ (SQL)
PostgreSQL

FerretDB converts MongoDB commands to SQL. For example:

  • db.users.find({ role: "admin" })SELECT * FROM users WHERE data->>'role' = 'admin'
  • db.users.insertOne({ name: "Alice" })INSERT INTO users (data) VALUES ('{"name":"Alice"}')

Setting Up FerretDB

Docker Compose (FerretDB + PostgreSQL):

yaml
version: '3'
services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: ferret
      POSTGRES_PASSWORD: ferret
      POSTGRES_DB: ferretdb
    volumes:
      - pgdata:/var/lib/postgresql/data

  ferretdb:
    image: ghcr.io/ferretdb/ferretdb:latest
    environment:
      FERRETDB_POSTGRESQL_URL: postgres://ferret:ferret@postgres:5432/ferretdb
    ports:
      - "27017:27017"
    depends_on:
      - postgres

volumes:
  pgdata:
bash
docker-compose up -d

# Connect with mongosh (standard MongoDB shell)
mongosh "mongodb://127.0.0.1:27017/myapp?authMechanism=PLAIN"

Connecting Your Application

Because FerretDB is MongoDB-compatible, you use the standard MongoDB driver:

bash
npm install mongodb
javascript
import { MongoClient } from 'mongodb';

// Same connection string as MongoDB
const client = new MongoClient('mongodb://127.0.0.1:27017/myapp');
await client.connect();

const db = client.db('myapp');
const users = db.collection('users');

// Standard MongoDB operations — work with FerretDB unchanged
await users.insertOne({ name: 'Alice', email: 'alice@example.com' });
const alice = await users.findOne({ name: 'Alice' });
console.log(alice);

No code changes are required to switch from MongoDB to FerretDB.

Example

javascript
// FerretDB uses the standard MongoDB Node.js driver
import { MongoClient } from 'mongodb';

const client = new MongoClient('mongodb://localhost:27017/myapp');
await client.connect();

const db = client.db('myapp');
const products = db.collection('products');

// All standard MongoDB operations work
await products.insertMany([
  { name: 'Widget A', price: 9.99, category: 'tools', stock: 100 },
  { name: 'Widget B', price: 19.99, category: 'tools', stock: 50 },
]);

const results = await products
  .find({ category: 'tools', price: { $lt: 15 } })
  .sort({ price: 1 })
  .toArray();

console.log(results);
// Data is actually stored in PostgreSQL under the hood

Want to run this code interactively?

Try in Compiler