Core Concepts
MongoDB Compatibility and Differences
Understand what FerretDB supports, where it differs from MongoDB, and how to migrate an existing MongoDB application.
FerretDB Compatibility Status
FerretDB aims to be compatible with the MongoDB 6.x API. As of 2025, most common MongoDB operations are supported:
Fully Supported
- CRUD operations:
insertOne,insertMany,find,findOne,updateOne,updateMany,deleteOne,deleteMany - Comparison operators:
$eq,$ne,$gt,$gte,$lt,$lte,$in,$nin - Logical operators:
$and,$or,$not,$nor - Update operators:
$set,$unset,$inc,$push,$pull,$addToSet - Aggregation pipeline:
$match,$group,$sort,$limit,$skip,$project - Indexes: single field, compound, text (basic)
Not Yet Supported / Limited
- Transactions (multi-document) — in progress
- Change Streams — not supported
- Full aggregation pipeline coverage — some operators missing
- Geospatial queries — basic support
- GridFS — not supported
Check the [FerretDB compatibility table](https://docs.ferretdb.io/reference/supported-commands/) for the current status.
Practical Differences
ObjectId Handling
FerretDB generates ObjectIds that look different internally but behave the same from the application's perspective:
// This works identically on MongoDB and FerretDB
const result = await collection.insertOne({ name: 'Alice' });
console.log(result.insertedId); // ObjectId - same APIData Inspection in PostgreSQL
The biggest operational difference: you can inspect and query your data directly in PostgreSQL:
-- In psql, FerretDB stores documents in a JSONB column
SELECT * FROM myapp.users LIMIT 5;
-- Query with PostgreSQL's JSONB operators directly
SELECT data->>'name', data->>'email'
FROM myapp.users
WHERE data->>'role' = 'admin';
-- This is powerful for debugging, analytics, and migrationsMigrating from MongoDB to FerretDB
Step 1: Export from MongoDB
mongodump --uri "mongodb://your-mongo/myapp" --out ./dumpStep 2: Start FerretDB
docker-compose up -dStep 3: Import to FerretDB
mongorestore --uri "mongodb://localhost:27017/myapp" ./dump/myappStep 4: Update connection string
// Before
const client = new MongoClient('mongodb://mongo-host:27017/myapp');
// After
const client = new MongoClient('mongodb://localhost:27017/myapp');
// That's it — no other code changes for supported operationsFerretDB in AI Applications
FerretDB is a good choice for AI applications that:
- Already use MongoDB and want to migrate to a truly open-source stack
- Want to store document data (like conversation histories or prompt templates) alongside relational data in PostgreSQL
- Need SQL analytics on document data without a separate data warehouse
// Store LLM conversation history as documents
const conversations = db.collection('conversations');
await conversations.insertOne({
sessionId: 'sess-abc123',
userId: 'user-42',
messages: [
{ role: 'user', content: 'Explain RAG pipelines', ts: new Date() },
{ role: 'assistant', content: 'RAG (Retrieval Augmented Generation)...', ts: new Date() },
],
model: 'claude-opus-4-5',
tokenCount: 450,
createdAt: new Date(),
});
// Retrieve conversation history
const history = await conversations
.find({ userId: 'user-42' })
.sort({ createdAt: -1 })
.limit(10)
.toArray();
// Meanwhile, in PostgreSQL you can run analytics:
// SELECT data->>'model', COUNT(*), SUM((data->>'tokenCount')::int)
// FROM myapp.conversations
// GROUP BY data->>'model';FerretDB vs. DocumentDB (Amazon)
Amazon DocumentDB is also MongoDB-compatible but is closed-source, AWS-only, and has its own compatibility gaps. FerretDB is open-source, runs anywhere PostgreSQL runs, and is community-driven. For teams avoiding vendor lock-in, FerretDB is the more principled choice.
Example
// Migration test: run this against both MongoDB and FerretDB
import { MongoClient } from 'mongodb';
async function testCompatibility(uri) {
const client = new MongoClient(uri);
await client.connect();
const col = client.db('test').collection('items');
await col.deleteMany({}); // Clean slate
// CRUD
await col.insertMany([
{ name: 'A', score: 10, tags: ['x', 'y'] },
{ name: 'B', score: 20, tags: ['y', 'z'] },
{ name: 'C', score: 30, tags: ['x', 'z'] },
]);
const docs = await col.find({ score: { $gt: 10 } }).sort({ score: -1 }).toArray();
console.log('Query result count:', docs.length); // Should be 2
await col.updateOne({ name: 'A' }, { $inc: { score: 5 } });
const updated = await col.findOne({ name: 'A' });
console.log('Updated score:', updated.score); // Should be 15
await client.close();
}Want to run this code interactively?
Try in Compiler