Skip to main content
โšก Calmops

MongoDB Operations: Deployment, Scaling, and Management

Introduction

Running MongoDB in production requires understanding its operational capabilities. MongoDB provides robust features for high availability, horizontal scaling, and data protection. This guide covers the essential operational aspects: replica sets for redundancy, sharding for horizontal scalability, backup strategies, security configuration, and monitoring practices.

Whether you are deploying a single development instance or managing a large production cluster, these operational practices will help ensure your MongoDB deployment is reliable, secure, and performant.

Replica Sets

Replica sets provide high availability by maintaining multiple copies of your data across different servers. If the primary node fails, an automatic election promotes a secondary to primary, ensuring continuous operation.

Understanding Replica Set Architecture

A replica set consists of multiple MongoDB instances:

  • Primary - Handles all write operations
  • Secondary - Replicates data from primary, serves reads
  • Arbiter - Participates in elections without storing data
// Replica set configuration
{
  _id: 'rs0',
  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 }
  ]
}

Setting Up a Replica Set

# Initialize replica set on primary
mongosh --eval '
  rs.initiate({
    _id: "rs0",
    members: [
      { host: "mongodb1.example.com:27017" },
      { host: "mongodb2.example.com:27017" },
      { host: "mongodb3.example.com:27017" }
    ]
  })
'

# Check replica set status
rs.status()

# Add a member
rs.add("mongodb4.example.com:27017")

# Remove a member
rs.remove("mongodb3.example.com:27017")

Read and Write Concerns

Configure how reads and writes behave across the replica set.

// Strong consistency (default) - reads from primary
db.products.find().readPref('primary')

// Read from nearest replica
db.products.find().readPref('nearest')

// Read from secondaries with latency threshold
db.products.find().readPref('secondaryPreferred', [{ maxStalenessSeconds: 90 }])

// Acknowledged writes (default)
db.products.insertOne({ name: 'Product' }, { writeConcern: { w: 'majority' } })

// Journaled writes
db.products.insertOne({ name: 'Product' }, { writeConcern: { j: true, wtimeout: 5000 } })

Failover Handling

Configure automatic failover and connection handling.

// Connection string with replica set
const uri = 'mongodb://mongodb1.example.com:27017,mongodb2.example.com:27017,mongodb3.example.com:27017/?replicaSet=rs0';

const client = new MongoClient(uri, {
  // Retry writes on transient failures
  retryWrites: true,
  // Retry reads on network errors
  retryReads: true,
  // Connect timeout
  serverSelectionTimeoutMS: 30000
});

Sharding

Sharding enables horizontal scaling by distributing data across multiple servers.

Sharding Concepts

  • Shard - A subset of the data, typically a replica set
  • Config Servers - Metadata about the cluster
  • Mongos - Query router that routes queries to appropriate shards

Setting Up a Sharded Cluster

# Start config server
mongod --configsvr --replSet configReplSet --dbpath /data/config --port 27019

# Start shard servers
mongod --shardsvr --replSet shardReplSet1 --dbpath /data/shard1 --port 27018
mongod --shardsvr --replSet shardReplSet2 --dbpath /data/shard2 --port 27018

# Start mongos (query router)
mongos --configdb configReplSet/config1.example.com:27019,config2.example.com:27019 --port 27017

Shard Keys

Choose shard keys carefully, as they cannot be changed after collection sharding.

// Enable sharding on database
sh.enableSharding("myapp")

// Shard collection with hashed shard key (good for sequential writes)
sh.shardCollection("myapp.orders", { _id: "hashed" })

// Shard collection with compound key (good for range queries)
sh.shardCollection("myapp.products", { category: 1, sku: 1 })

// Shard collection with region-based key
sh.shardCollection("myapp.users", { country: 1, user_id: 1 })

Managing Chunks

# Check chunk distribution
sh.status()

# Split chunk at median
sh.splitAt("myapp.products", { category: "Electronics" })

# Move chunk to specific shard
sh.moveChunk("myapp.products", { category: "Electronics" }, "shard0001")

Backup and Restore

Protecting your data requires regular backups and tested restore procedures.

###mongodump and mongorestore

# Create backup of entire database
mongodump --uri="mongodb://user:password@localhost:27017/mydb" --out=/backups/$(date +%Y%m%d)

# Backup with query filter
mongodump --uri="mongodb://user:password@localhost:27017/mydb" \
  --collection=orders \
  --query='{"created_at": {"$gte": {"$date": "2026-01-01T00:00:00Z"}}}' \
  --out=/backups/orders_2026

# Restore from backup
mongorestore --uri="mongodb://user:password@localhost:27017/mydb" /backups/20260311/mydb

# Restore specific collection
mongorestore --uri="mongodb://user:password@localhost:27017/mydb" \
  --collection=orders \
  /backups/orders_2026/mydb/orders.bson

Atlas Backup

If using MongoDB Atlas, enable cloud backups.

// Configure Atlas backup (via Atlas UI or CLI)
// - Continuous backups with point-in-time recovery
// - Snapshots (daily, weekly, monthly)
// - Cloud provider snapshots

Point-in-Time Recovery

// Using oplog for point-in-time recovery
// 1. Get timestamp from oplog
db.oplog.rs.find().sort({ ts: -1 }).limit(1)

// 2. Restore to specific time
mongorestore --uri="mongodb://user:password@localhost:27017/mydb" \
  --oplogReplay \
  --oplogLimit="2026-03-11T10:30:00" \
  /backups/full_backup

Security

MongoDB provides comprehensive security features including authentication, authorization, and encryption.

Authentication

Enable and configure authentication.

// Create user administrator
use admin
db.createUser({
  user: 'adminUser',
  pwd: 'securePassword',
  roles: [
    { role: 'userAdminAnyDatabase', db: 'admin' },
    { role: 'readWriteAnyDatabase', db: 'admin' }
  ]
})

// Enable authentication in mongod.conf
// security:
//   authorization: enabled
//   keyFile: /etc/mongodb/keyfile

// Create application user
use myapp
db.createUser({
  user: 'appUser',
  pwd: 'appPassword',
  roles: [
    { role: 'readWrite', db: 'myapp' },
    { role: 'read', db: 'reporting' }
  ]
})

// Authenticate in mongosh
db.auth('appUser', 'appPassword')

// Connection with authentication
const uri = 'mongodb://appUser:appPassword@localhost:27017/myapp';

Role-Based Access Control

Create custom roles for fine-grained permissions.

// Create custom role with specific privileges
db.adminCommand({
  createRole: 'dataAnalyst',
  privileges: [
    {
      resource: { db: 'myapp', collection: 'orders' },
      actions: ['find', 'aggregate']
    },
    {
      resource: { db: 'myapp', collection: 'products' },
      actions: ['find']
    }
  ],
  roles: []
})

// Assign role to user
db.grantRolesToUser('analystUser', ['dataAnalyst'])

// List user's roles
db.getUser('analystUser')

Encryption

Enable encryption at rest and in transit.

# mongod.conf for encryption
security:
  enableEncryption: true
  encryptionKeyFile: /etc/mongodb/encryption.key

# TLS/SSL configuration
net:
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/mongodb/server.pem
    CAFile: /etc/mongodb/ca.pem

Network Security

Limit network exposure.

# Bind to specific IP
net:
  bindIp: "127.0.0.1,10.0.0.1"

# Enable firewall
sudo ufw allow from 10.0.0.0/24 to any port 27017

Monitoring

Effective monitoring helps identify issues before they impact users.

MongoDB Logs

# View recent logs
tail -f /var/log/mongodb/mongod.log

# Analyze slow queries
grep "slow query" /var/log/mongodb/mongod.log

# Check for errors
grep -i error /var/log/mongodb/mongod.log | tail -50

Database Profiler

Enable profiling to track slow operations.

// Enable profiler
db.setProfilingLevel(1, { slowms: 100 })  // Log operations > 100ms

// Query profiler data
db.system.profile.find({ millis: { $gt: 1000 } }).sort({ ts: -1 }).limit(10)

// Disable profiler
db.setProfilingLevel(0)

Atlas Monitoring

If using Atlas, leverage built-in monitoring.

// Monitor via Atlas APIs
// - Connection counts
// - Query performance
// - Memory usage
// - Disk I/O
// - Replication lag

Custom Metrics

// Get server status
db.serverStatus()

// Get collection stats
db.products.stats()

// Get index stats
db.products.getIndexes()

// Check replication lag
rs.printSlaveReplicationInfo()

Performance Tuning

Optimize MongoDB for your workload.

Memory Configuration

// WiredTiger cache configuration
// Target: (RAM - 1GB) / 2
// In mongod.conf:
storage:
  wiredTiger:
    engineConfig:
      cacheSizeGB: 8

Connection Pooling

Configure appropriate connection pool sizes.

const client = new MongoClient(uri, {
  maxPoolSize: 10,        // Maximum connections
  minPoolSize: 2,          // Minimum connections
  maxIdleTimeMS: 30000,   // Connection timeout
  waitQueueTimeoutMS: 3000 // Queue timeout
});

Query Optimization

// Use projection to limit fields returned
db.products.find({ category: 'Electronics' }, { name: 1, price: 1 })

// Use limit for pagination
db.products.find({ category: 'Electronics' }).limit(20).skip(40)

// Use explain to analyze queries
db.products.find({ category: 'Electronics', price: { $lt: 100 } })
  .sort({ price: 1 })
  .explain('executionStats')

Maintenance

Regular maintenance keeps your deployment healthy.

Compact Collections

// Compact collection (reclaims disk space)
db.runCommand({ compact: 'products' })

// Compact with force (allows on single shard)
db.runCommand({ compact: 'products', force: true })

Repair Databases

// Repair database (after unclean shutdown)
db.repairDatabase()

Index Maintenance

// Rebuild indexes
db.products.reIndex()

// Drop unused indexes
db.products.dropIndex('unnecessary_index_name')

Deployment Options

Choose the right deployment model for your needs.

Self-Managed

# Docker Compose for development
version: '3.8'
services:
  mongodb:
    image: mongo:8.0
    ports:
      - "27017:27017"
    volumes:
      - mongodb_data:/data/db
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: password

Atlas Serverless

// Create serverless instance via Atlas API
// Pay only for resources consumed
// Ideal for variable workloads

Atlas Dedicated

// Dedicated cluster with
// - Multi-region deployment
// - Sharding
// - Advanced security
// - Managed backups

Disaster Recovery

Prepare for worst-case scenarios.

Offsite Backups

# Backup to cloud storage
mongodump --uri="mongodb://admin:pass@localhost:27017" \
  --archive="/s3/bucket/mongodb-backup.gz" \
  --gzip

Runbook Template

Create runbooks for common scenarios.

## Database Failover Runbook

1. Check replica set status
   rs.status()

2. Identify failed node
   - Note: If primary fails, election will occur automatically

3. For manual failover:
   rs.stepDown()

4. Verify new primary elected
   rs.status().members.filter(m => m.stateStr === 'PRIMARY')

5. Address failed node
   - Check logs
   - Fix issue
   - Restart or replace

External Resources

Conclusion

MongoDB operations require careful attention to high availability, scaling, security, and monitoring. This guide covered the essential operational practices: replica sets for redundancy, sharding for horizontal scalability, backup strategies, security configuration, and monitoring approaches.

By following these operational best practices, you can ensure your MongoDB deployment is reliable, secure, and performant. Regular maintenance, monitoring, and testing of backup procedures are essential for production environments.

In the next article, we will explore MongoDB’s internal architecture, understanding how the WiredTiger storage engine works and how MongoDB handles data internally.

Comments