Skip to main content

MongoDB Replication

Replica Set Setup

Initialize Replica Set

// Initialize replica set
rs.initiate({
_id: "myReplicaSet",
members: [
{ _id: 0, host: "mongodb1.example.com:27017", priority: 2 },
{ _id: 1, host: "mongodb2.example.com:27017", priority: 1 },
{ _id: 2, host: "mongodb3.example.com:27017", priority: 1 }
]
});

// Simple single-server replica set (development)
rs.initiate();

Add Members to Replica Set

// Add secondary member
rs.add("mongodb4.example.com:27017");

// Add member with specific configuration
rs.add({
_id: 3,
host: "mongodb4.example.com:27017",
priority: 0.5,
votes: 1
});

// Add arbiter (voting only, no data)
rs.addArb("arbiter.example.com:27017");

Remove Members

// Remove member
rs.remove("mongodb4.example.com:27017");

// Remove by member ID
rs.remove(3);

Replica Set Management

Check Replica Set Status

// Get replica set status
rs.status();

// Get replica set configuration
rs.conf();

// Check if current node is primary
rs.isMaster();

// Get replication info
db.getReplicationInfo();

// Check slave status
db.printSlaveReplicationInfo();

Replica Set Configuration

// Get current configuration
config = rs.conf();

// Modify configuration
config.members[1].priority = 2;
config.members[2].hidden = true;
config.version++;

// Apply configuration changes
rs.reconfig(config);

// Force reconfiguration (use with caution)
rs.reconfig(config, {force: true});

Member Roles and Properties

// Priority settings (0-1000, higher = more likely to be primary)
{
_id: 0,
host: "mongodb1.example.com:27017",
priority: 2 // High priority for primary
}

// Hidden member (not visible to applications)
{
_id: 1,
host: "mongodb2.example.com:27017",
priority: 0,
hidden: true // Hidden from read operations
}

// Delayed member (for backup/recovery)
{
_id: 2,
host: "mongodb3.example.com:27017",
priority: 0,
hidden: true,
slaveDelay: 3600 // 1 hour delay
}

// Arbiter (voting only)
{
_id: 3,
host: "arbiter.example.com:27017",
arbiterOnly: true
}

// Non-voting member
{
_id: 4,
host: "mongodb4.example.com:27017",
votes: 0,
priority: 0
}

Read Preferences

Configure Read Preferences

// Primary (default)
db.users.find().readPref("primary");

// Primary preferred
db.users.find().readPref("primaryPreferred");

// Secondary
db.users.find().readPref("secondary");

// Secondary preferred
db.users.find().readPref("secondaryPreferred");

// Nearest (lowest latency)
db.users.find().readPref("nearest");

Read Preference with Tags

// Configure member tags first
config = rs.conf();
config.members[0].tags = { "region": "us-east", "datacenter": "primary" };
config.members[1].tags = { "region": "us-west", "datacenter": "secondary" };
config.version++;
rs.reconfig(config);

// Read from specific tagged members
db.users.find().readPref("secondary", [{ "region": "us-east" }]);

// Multiple tag sets (fallback)
db.users.find().readPref("secondary", [
{ "region": "us-east", "datacenter": "primary" },
{ "region": "us-west" },
{} // Fallback to any secondary
]);

Write Concerns

Write Concern Levels

// Default write concern
db.users.insertOne({name: "John"});

// Acknowledged write (w: 1)
db.users.insertOne(
{name: "John"},
{writeConcern: {w: 1}}
);

// Majority write concern
db.users.insertOne(
{name: "John"},
{writeConcern: {w: "majority", j: true}}
);

// Specific number of acknowledgments
db.users.insertOne(
{name: "John"},
{writeConcern: {w: 2, wtimeout: 5000}}
);

// Unacknowledged write (fire and forget)
db.users.insertOne(
{name: "John"},
{writeConcern: {w: 0}}
);

Custom Write Concern Rules

// Define custom write concern
config = rs.conf();
config.settings = {
getLastErrorModes: {
"allDCs": {
"datacenter": 2
},
"majority": {
"region": 2
}
}
};
config.version++;
rs.reconfig(config);

// Use custom write concern
db.users.insertOne(
{name: "John"},
{writeConcern: {w: "allDCs", wtimeout: 10000}}
);

Failover and Elections

Manual Failover

// Step down primary (triggers election)
rs.stepDown(60); // Step down for 60 seconds

// Step down immediately
rs.stepDown();

// Freeze member (prevent it from becoming primary)
rs.freeze(120); // Freeze for 120 seconds

// Unfreeze member
rs.freeze(0);

Election Control

// Check election status
db.adminCommand({replSetGetStatus: 1}).members.forEach(
function(member) {
print(member.name + ": " + member.stateStr);
}
);

// Force election (use with extreme caution)
db.adminCommand({replSetStepDown: 10, force: true});

Monitoring Replication

Replication Lag

// Check replication lag
rs.printSlaveReplicationInfo();

// Get detailed lag information
db.adminCommand({replSetGetStatus: 1}).members.forEach(
function(member) {
if (member.state !== 1) { // Not primary
var lag = (new Date() - member.optimeDate) / 1000;
print(member.name + " lag: " + lag + " seconds");
}
}
);

Oplog Information

// Switch to local database
use local;

// Check oplog size
db.oplog.rs.stats().maxSize;

// Get oplog information
db.getReplicationInfo();

// Find oplog entries
db.oplog.rs.find().sort({$natural: -1}).limit(5);

// Count oplog entries
db.oplog.rs.count();

Health Checks

// Health check script
function replicaSetHealthCheck() {
var status = rs.status();
var healthy = true;
var issues = [];

status.members.forEach(function(member) {
if (member.health !== 1) {
healthy = false;
issues.push(member.name + " is unhealthy");
}

if (member.state === 1) { // Primary
print("Primary: " + member.name);
} else if (member.state === 2) { // Secondary
var lag = (status.date - member.optimeDate) / 1000;
if (lag > 10) { // More than 10 seconds lag
issues.push(member.name + " has high replication lag: " + lag + "s");
}
}
});

if (healthy && issues.length === 0) {
print("Replica set is healthy");
} else {
print("Issues found:");
issues.forEach(function(issue) {
print("- " + issue);
});
}
}

// Run health check
replicaSetHealthCheck();

Backup and Restore

Backup from Secondary

# Backup from secondary to avoid impacting primary
mongodump --host secondary.example.com:27017 \
--username backup_user \
--password backup_pass \
--authenticationDatabase admin \
--out /backup/$(date +%Y%m%d_%H%M%S)

# Backup specific database
mongodump --host secondary.example.com:27017 \
--db myapp \
--out /backup/myapp_$(date +%Y%m%d)

Point-in-Time Recovery

# Stop MongoDB on target server
sudo systemctl stop mongod

# Restore base backup
mongorestore --host localhost:27017 \
--drop \
/backup/base_backup/

# Replay oplog to specific timestamp
mongorestore --host localhost:27017 \
--oplogReplay \
--oplogLimit 1640995200:1 \
/backup/oplog_backup/

Configuration Examples

Production Replica Set (3 nodes)

rs.initiate({
_id: "production-rs",
members: [
{
_id: 0,
host: "mongo-primary.prod.com:27017",
priority: 2,
tags: { "region": "us-east", "datacenter": "primary" }
},
{
_id: 1,
host: "mongo-secondary1.prod.com:27017",
priority: 1,
tags: { "region": "us-east", "datacenter": "secondary" }
},
{
_id: 2,
host: "mongo-secondary2.prod.com:27017",
priority: 1,
tags: { "region": "us-west", "datacenter": "secondary" }
}
],
settings: {
chainingAllowed: false,
heartbeatIntervalMillis: 2000,
heartbeatTimeoutSecs: 10,
electionTimeoutMillis: 10000,
catchUpTimeoutMillis: 60000,
getLastErrorModes: {
"crossDataCenter": { "datacenter": 2 }
}
}
});

Development Replica Set (single node)

# Start MongoDB with replica set
mongod --replSet dev-rs --dbpath /data/db --port 27017

# Initialize single-member replica set
mongosh --eval "rs.initiate()"

Driver Configuration

Python (PyMongo)

from pymongo import MongoClient, ReadPreference

# Replica set connection
client = MongoClient(
'mongodb://user:pass@mongo1:27017,mongo2:27017,mongo3:27017/mydb?replicaSet=production-rs',
readPreference=ReadPreference.SECONDARY_PREFERRED,
w='majority',
j=True,
serverSelectionTimeoutMS=5000
)

# Read from secondary
db = client.mydb
users = db.users.with_options(
read_preference=ReadPreference.SECONDARY
)

Node.js

const { MongoClient } = require('mongodb');

const uri = 'mongodb://user:pass@mongo1:27017,mongo2:27017,mongo3:27017/mydb?replicaSet=production-rs';

const client = new MongoClient(uri, {
readPreference: 'secondaryPreferred',
w: 'majority',
j: true,
serverSelectionTimeoutMS: 5000,
heartbeatFrequencyMS: 10000
});

// Use specific read preference
const db = client.db('mydb');
const users = db.collection('users').withReadPreference('secondary');