docs-src/docs/replication-mongodb.md
import {Tabs} from '@site/src/components/tabs'; import {Steps} from '@site/src/components/steps'; import {VideoBox} from '@site/src/components/video-box'; import {RxdbMongoDiagramPlain} from '@site/src/components/mongodb-sync'; import {HeadlineWithIcon} from '@site/src/components/headline-with-icon';
The MongoDB Replication Plugin for RxDB delivers seamless, two-way synchronization between MongoDB and RxDB, enabling real-time updates and offline-first functionality for your applications. Built on MongoDB Change Streams, it supports both Atlas and self-hosted deployments, ensuring your data stays consistent across every device and service.
Behind the scenes, the plugin is powered by the RxDB Sync Engine, which manages the complexities of real-world data replication for you. It automatically handles conflict detection and resolution, maintains precise checkpoints for incremental updates, and gracefully manages transitions between offline and online states. This means you don't need to manually implement retry logic, reconcile divergent changes, or worry about data loss during connectivity drops, the Sync Engine ensures consistency and reliability in every sync cycle.
The plugin operates in a three-tier architecture: Clients connect to RxServer, which in turn connects to MongoDB. RxServer streams changes from MongoDB to connected clients and pushes client-side updates back to MongoDB.
For the client side, RxServer exposes a replication endpoint over WebSocket or HTTP, which your RxDB-powered applications can consume.
The following diagram illustrates the flow of updates between clients, RxServer, and MongoDB in a live synchronization setup:
<RxdbMongoDiagramPlain dbIcon="/files/icons/mongodb-icon.svg" dbLabel="MongoDB" />:::note The MongoDB Replication Plugin is optimized for Node.js environments (e.g., when RxDB runs within RxServer or other backend services). Direct connections from browsers or mobile apps to MongoDB are not supported because MongoDB does not use HTTP as its wire protocol and requires a driver-level connection to a replica set or sharded cluster. :::
In your JavaScript project, install the RxDB libraries and the MongoDB node.js driver:
npm install rxdb rxdb-server mongodb --save
As first step, you need access to a running MongoDB Server. This can be done by either running a server locally or using the Atlas Cloud. Notice that we need to have a replica set because only on these, the MongoDB changestream can be used.
<Tabs>If you have installed MongoDB locally, you can start the server with this command:
mongod --replSet rs0 --bind_ip_all
If you have docker installed, you can start a container that runs the MongoDB server:
docker run -p 27017:27017 -p 27018:27018 -p 27019:27019 --rm --name rxdb-mongodb mongo:8.0.4 mongod --replSet rs0 --bind_ip_all
Learn here how to create a MongoDB atlas account and how to start a MongoDB cluster that runs in the cloud:
<center> <VideoBox videoId="bBA9rUdqmgY" title="Create MongoDB Atlas Server" duration="19:55" /> </center> </Tabs>After this step you should have a valid
connection string that points to a running
MongoDB Server like
mongodb://localhost:27017/.
On your MongoDB server, make sure to create a database and a collection.
//> server.ts
import { MongoClient } from 'mongodb';
const mongoClient = new MongoClient(
'mongodb://localhost:27017/?directConnection=true'
);
const mongoDatabase = mongoClient.db('my-database');
await mongoDatabase.createCollection('my-collection', {
changeStreamPreAndPostImages: { enabled: true }
});
:::note
To observe document deletions on the
changestream, changeStreamPreAndPostImages
must be enabled. This is not required if you
have an insert/update-only collection where
no documents are deleted ever.
:::
Now we create an RxDB database and a collection. In this example the memory storage, in production you would use a persistent storage instead.
//> server.ts
import { createRxDatabase, addRxPlugin } from 'rxdb';
import { getRxStorageMemory } from 'rxdb/plugins/storage-memory';
// Create server-side RxDB instance
const db = await createRxDatabase({
name: 'serverdb',
storage: getRxStorageMemory()
});
// Add your collection schema
await db.addCollections({
humans: {
schema: {
version: 0,
primaryKey: 'passportId',
type: 'object',
properties: {
passportId: { type: 'string', maxLength: 100 },
firstName: { type: 'string' },
lastName: { type: 'string' }
},
required: ['passportId', 'firstName', 'lastName']
}
}
});
Now we can start a replication that does a two-way replication between the RxDB Collection and the MongoDB Collection.
//> server.ts
import { replicateMongoDB } from 'rxdb/plugins/replication-mongodb';
const replicationState = replicateMongoDB({
mongodb: {
collectionName: 'my-collection',
connection: 'mongodb://localhost:27017',
databaseName: 'my-database'
},
collection: db.humans,
replicationIdentifier: 'humans-mongodb-sync',
pull: { batchSize: 50 },
push: { batchSize: 50 },
live: true
});
:::note You can do many things with the replication state
The RxMongoDBReplicationState which is
returned from replicateMongoDB() allows
you to run all functionality of the normal
RxReplicationState like
observing errors or doing start/stop
operations.
:::
Now that we have a RxDatabase and Collection that is replicated with MongoDB, we can spawn a RxServer on top of it. This server can then be used by client devices to connect.
//> server.ts
import { createRxServer } from 'rxdb-server/plugins/server';
import { RxServerAdapterExpress } from 'rxdb-server/plugins/adapter-express';
const server = await createRxServer({
database: db,
adapter: RxServerAdapterExpress,
port: 8080,
cors: '*'
});
const endpoint = server.addReplicationEndpoint({
name: 'humans',
collection: db.humans
});
console.log('Replication endpoint:', `http://localhost:8080/${endpoint.urlPath}`);
// do not forget to start the server!
await server.start();
On the client-side we create the exact same RxDatabase and collection and then replicate it with the replication endpoint of the RxServer.
//> client.ts
import { createRxDatabase } from 'rxdb';
import { getRxStorageDexie } from 'rxdb/plugins/storage-dexie';
import { replicateServer } from 'rxdb-server/plugins/replication-server';
const db = await createRxDatabase({
name: 'mydb-client',
storage: getRxStorageDexie()
});
await db.addCollections({
humans: {
schema: {
version: 0,
primaryKey: 'passportId',
type: 'object',
properties: {
passportId: { type: 'string', maxLength: 100 },
firstName: { type: 'string' },
lastName: { type: 'string' }
},
required: ['passportId', 'firstName', 'lastName']
}
}
});
// Start replication to the RxServer endpoint printed by the server:
// e.g. http://localhost:8080/humans/0
const replicationState = replicateServer({
replicationIdentifier: 'humans-rxserver',
collection: db.humans,
url: 'http://localhost:8080/humans/0',
live: true,
pull: { batchSize: 50 },
push: { batchSize: 50 }
});