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
Your App
↓ (MongoDB wire protocol)
FerretDB (proxy)
↓ (SQL)
PostgreSQLFerretDB 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):
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: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:
npm install mongodbimport { 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
// 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 hoodWant to run this code interactively?
Try in Compiler