MongoDB powers over 37,000 organizations and stores more than 6 trillion documents worldwide, serving as the backbone for applications like Adobe, eBay, Forbes, and Toyota. As the leading document database, MongoDB has revolutionized how developers work with data through its flexible schema design and horizontal scaling capabilities. This comprehensive guide shows you how to deploy, secure, optimize, and scale MongoDB for production in 2025.

Why MongoDB Dominates NoSQL Databases

MongoDB has become the most popular NoSQL database because of its:

  • Document-based architecture: Natural fit for modern applications
  • Flexible schema: Adapt to changing requirements without migrations
  • Horizontal scaling: Built-in sharding for massive scale
  • Rich query language: Powerful aggregation framework
  • High availability: Automatic failover with replica sets
  • Developer productivity: Intuitive document model matches object-oriented programming

Production MongoDB Architecture

MongoDB Replica Set Configuration

# mongod.conf - Production replica set member configuration
storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true
  wiredTiger:
    engineConfig:
      cacheSizeGB: 8
      journalCompressor: snappy
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: snappy
    indexConfig:
      prefixCompression: true

systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log
  logRotate: rename
  component:
    accessControl:
      verbosity: 1
    command:
      verbosity: 1
    query:
      verbosity: 1
    write:
      verbosity: 1

net:
  port: 27017
  bindIp: 0.0.0.0
  maxIncomingConnections: 2000
  compression:
    compressors: snappy,zstd,zlib
  ssl:
    mode: requireSSL
    PEMKeyFile: /etc/ssl/mongodb/mongodb.pem
    CAFile: /etc/ssl/mongodb/ca.pem
    allowConnectionsWithoutCertificates: false

processManagement:
  fork: true
  pidFilePath: /var/run/mongodb/mongod.pid
  timeZoneInfo: /usr/share/zoneinfo

security:
  authorization: enabled
  clusterAuthMode: x509
  javascriptEnabled: false

operationProfiling:
  mode: slowOp
  slowOpThresholdMs: 100
  slowOpSampleRate: 0.1

replication:
  replSetName: "myapp-rs"
  enableMajorityReadConcern: true

sharding:
  clusterRole: shardsvr

setParameter:
  enableLocalhostAuthBypass: false
  authenticationMechanisms: SCRAM-SHA-1,SCRAM-SHA-256
  maxLogSizeKB: 10240
  logLevel: 1
  wiredTigerConcurrentReadTransactions: 128
  wiredTigerConcurrentWriteTransactions: 128
  wiredTigerEngineRuntimeConfig: "cache_size=8GB,eviction=(threads_min=4,threads_max=4)"

Replica Set Initialization Script

// replica-set-init.js - Initialize MongoDB replica set
rs.initiate({
  _id: "myapp-rs",
  version: 1,
  term: 1,
  members: [
    {
      _id: 0,
      host: "mongo-primary:27017",
      priority: 2,
      tags: { region: "us-east-1", datacenter: "dc1", role: "primary" }
    },
    {
      _id: 1,
      host: "mongo-secondary1:27017", 
      priority: 1,
      tags: { region: "us-east-1", datacenter: "dc2", role: "secondary" }
    },
    {
      _id: 2,
      host: "mongo-secondary2:27017",
      priority: 1,
      tags: { region: "us-west-2", datacenter: "dc3", role: "secondary" }
    },
    {
      _id: 3,
      host: "mongo-arbiter:27017",
      arbiterOnly: true,
      priority: 0,
      tags: { role: "arbiter" }
    }
  ],
  settings: {
    chainingAllowed: true,
    heartbeatIntervalMillis: 2000,
    heartbeatTimeoutSecs: 10,
    electionTimeoutMillis: 10000,
    catchUpTimeoutMillis: 60000,
    getLastErrorModes: {
      majorityDatacenter: {
        datacenter: 2
      }
    },
    getLastErrorDefaults: {
      w: "majority",
      wtimeout: 5000
    }
  }
});

// Wait for replica set to stabilize
sleep(10000);

// Create admin user
use admin;
db.createUser({
  user: "admin",
  pwd: passwordPrompt(),
  roles: [
    { role: "root", db: "admin" }
  ]
});

// Create application database and user
use myapp;
db.createUser({
  user: "appuser",
  pwd: passwordPrompt(), 
  roles: [
    { role: "readWrite", db: "myapp" },
    { role: "dbAdmin", db: "myapp" }
  ]
});

// Create monitoring user
use admin;
db.createUser({
  user: "monitoring",
  pwd: passwordPrompt(),
  roles: [
    { role: "clusterMonitor", db: "admin" },
    { role: "read", db: "local" }
  ]
});

// Configure read preferences for different use cases
rs.conf().members.forEach(function(member) {
  if (member.tags.role === "secondary") {
    // Configure secondary for analytics workloads
    db.adminCommand({
      "replSetSyncFrom": "mongo-primary:27017"
    });
  }
});

// Enable sharding preparation
use config;
sh.enableSharding("myapp");
sh.shardCollection("myapp.users", { "_id": "hashed" });
sh.shardCollection("myapp.orders", { "userId": 1, "createdAt": 1 });
sh.shardCollection("myapp.products", { "category": 1, "_id": 1 });

Sharding for Horizontal Scaling

Sharded Cluster Configuration

# mongos.conf - Query router configuration
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongos.log

net:
  port: 27017
  bindIp: 0.0.0.0

sharding:
  configDB: "config-rs/config1:27018,config2:27018,config3:27018"

security:
  keyFile: /opt/mongodb/keyfile
  clusterAuthMode: keyFile

processManagement:
  fork: true
# config-server.conf - Config server configuration  
storage:
  dbPath: /var/lib/mongodb-config
  journal:
    enabled: true

systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/config.log

net:
  port: 27018
  bindIp: 0.0.0.0

replication:
  replSetName: "config-rs"

sharding:
  clusterRole: configsvr

security:
  keyFile: /opt/mongodb/keyfile
  clusterAuthMode: keyFile

processManagement:
  fork: true

Sharding Strategy Implementation

// sharding-setup.js - Advanced sharding configuration
use admin;

// Add shard servers to cluster
sh.addShard("shard1-rs/shard1-primary:27017,shard1-secondary1:27017,shard1-secondary2:27017");
sh.addShard("shard2-rs/shard2-primary:27017,shard2-secondary1:27017,shard2-secondary2:27017");
sh.addShard("shard3-rs/shard3-primary:27017,shard3-secondary1:27017,shard3-secondary2:27017");

// Enable sharding for database
sh.enableSharding("myapp");

// Shard collections with appropriate strategies
// Hashed sharding for even distribution
sh.shardCollection("myapp.users", { "_id": "hashed" });

// Range sharding for time-series data
sh.shardCollection("myapp.events", { "timestamp": 1, "_id": 1 });

// Compound shard key for multi-tenant applications
sh.shardCollection("myapp.orders", { "tenantId": 1, "createdAt": 1 });

// Zone sharding for geographical distribution
sh.addShardToZone("shard1-rs", "us-east");
sh.addShardToZone("shard2-rs", "us-west"); 
sh.addShardToZone("shard3-rs", "eu-west");

// Configure zone ranges
sh.updateZoneKeyRange(
  "myapp.users",
  { "region": "us-east" },
  { "region": "us-east", "_id": MaxKey },
  "us-east"
);

sh.updateZoneKeyRange(
  "myapp.users", 
  { "region": "us-west" },
  { "region": "us-west", "_id": MaxKey },
  "us-west"
);

sh.updateZoneKeyRange(
  "myapp.users",
  { "region": "eu-west" },
  { "region": "eu-west", "_id": MaxKey },
  "eu-west"
);

// Pre-split chunks for better initial distribution
for (var i = 0; i < 100; i++) {
  sh.splitAt("myapp.events", { "timestamp": new Date(2024, 0, 1 + i) });
}

// Configure balancer settings
sh.setBalancerState(true);
sh.configureBalancer({
  activeWindow: {
    start: "01:00",
    stop: "05:00"
  },
  _secondaryThrottle: true
});

// Verify sharding status
sh.status();

Security Implementation

Authentication and Authorization

// security-setup.js - Comprehensive security configuration
use admin;

// Create roles for different access patterns
db.createRole({
  role: "appReadWrite",
  privileges: [
    {
      resource: { db: "myapp", collection: "" },
      actions: ["find", "insert", "update", "remove", "createIndex"]
    }
  ],
  roles: []
});

db.createRole({
  role: "appReadOnly", 
  privileges: [
    {
      resource: { db: "myapp", collection: "" },
      actions: ["find"]
    }
  ],
  roles: []
});

db.createRole({
  role: "analyticsRead",
  privileges: [
    {
      resource: { db: "myapp", collection: "events" },
      actions: ["find"]
    },
    {
      resource: { db: "myapp", collection: "users" },
      actions: ["find"]
    }
  ],
  roles: []
});

db.createRole({
  role: "backupOperator",
  privileges: [
    {
      resource: { cluster: true },
      actions: ["listCollections", "listIndexes"]
    },
    {
      resource: { db: "", collection: "" },
      actions: ["find"]
    }
  ],
  roles: ["backup"]
});

// Create users with appropriate roles
db.createUser({
  user: "app-prod",
  pwd: passwordPrompt(),
  roles: [
    { role: "appReadWrite", db: "myapp" }
  ],
  authenticationRestrictions: [
    {
      clientSource: ["10.0.1.0/24", "10.0.2.0/24"],
      serverAddress: ["10.0.1.100", "10.0.1.101", "10.0.1.102"]
    }
  ]
});

db.createUser({
  user: "app-readonly",
  pwd: passwordPrompt(),
  roles: [
    { role: "appReadOnly", db: "myapp" }
  ],
  authenticationRestrictions: [
    {
      clientSource: ["10.0.3.0/24"]
    }
  ]
});

db.createUser({
  user: "analytics-user",
  pwd: passwordPrompt(), 
  roles: [
    { role: "analyticsRead", db: "myapp" }
  ]
});

// Configure authentication mechanisms
db.runCommand({
  setParameter: 1,
  authenticationMechanisms: ["SCRAM-SHA-1", "SCRAM-SHA-256"]
});

// Enable auditing for security events
db.adminCommand({
  setParameter: 1,
  auditLog: {
    destination: "file",
    path: "/var/log/mongodb/audit.log",
    format: "JSON",
    filter: {
      $or: [
        { "atype": "authenticate" },
        { "atype": "authCheck", "param.command": { $in: ["find", "insert", "update", "delete"] } },
        { "atype": "createUser" },
        { "atype": "dropUser" },
        { "atype": "createRole" },
        { "atype": "dropRole" }
      ]
    }
  }
});

Network Security and Encryption

#!/bin/bash
# ssl-setup.sh - SSL/TLS certificate generation

# Create certificate authority
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca.pem \
  -subj "/C=US/ST=CA/L=San Francisco/O=MyCompany/OU=IT/CN=MongoDB-CA"

# Generate server certificate
openssl genrsa -out mongodb-key.pem 4096
openssl req -new -key mongodb-key.pem -out mongodb.csr \
  -subj "/C=US/ST=CA/L=San Francisco/O=MyCompany/OU=IT/CN=mongodb.mycompany.com"

# Sign server certificate
openssl x509 -req -in mongodb.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out mongodb.pem -days 365 \
  -extensions v3_req -extfile <(cat <<EOF
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = mongodb.mycompany.com
DNS.2 = mongo-primary
DNS.3 = mongo-secondary1
DNS.4 = mongo-secondary2
IP.1 = 10.0.1.100
IP.2 = 10.0.1.101
IP.3 = 10.0.1.102
EOF
)

# Combine certificate and key
cat mongodb.pem mongodb-key.pem > mongodb-combined.pem

# Generate client certificates for authentication
openssl genrsa -out client-key.pem 4096
openssl req -new -key client-key.pem -out client.csr \
  -subj "/C=US/ST=CA/L=San Francisco/O=MyCompany/OU=IT/CN=mongodb-client"

openssl x509 -req -in client.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out client.pem -days 365

cat client.pem client-key.pem > client-combined.pem

# Set proper permissions
chmod 600 *-key.pem
chmod 644 *.pem

# Create keyfile for replica set authentication
openssl rand -base64 756 > keyfile
chmod 600 keyfile
chown mongodb:mongodb keyfile

echo "SSL certificates generated successfully"
echo "Copy ca.pem and mongodb-combined.pem to MongoDB servers"
echo "Copy keyfile to all replica set members"

Performance Optimization

Database Indexing Strategies

// indexing-strategy.js - Comprehensive indexing for performance
use myapp;

// User collection indexes
db.users.createIndex({ "email": 1 }, { unique: true, background: true });
db.users.createIndex({ "username": 1 }, { unique: true, sparse: true, background: true });
db.users.createIndex({ "status": 1, "lastLogin": -1 }, { background: true });
db.users.createIndex({ "createdAt": -1 }, { background: true });
db.users.createIndex({ "location.country": 1, "location.city": 1 }, { background: true });

// Text search index for user profiles
db.users.createIndex({
  "username": "text",
  "profile.firstName": "text", 
  "profile.lastName": "text",
  "profile.bio": "text"
}, {
  name: "user_text_search",
  weights: {
    "username": 10,
    "profile.firstName": 5,
    "profile.lastName": 5,
    "profile.bio": 1
  },
  background: true
});

// Orders collection indexes
db.orders.createIndex({ "userId": 1, "status": 1 }, { background: true });
db.orders.createIndex({ "createdAt": -1 }, { background: true });
db.orders.createIndex({ "status": 1, "updatedAt": -1 }, { background: true });
db.orders.createIndex({ "totalAmount": 1 }, { background: true, sparse: true });

// Compound index for order queries
db.orders.createIndex({ 
  "userId": 1, 
  "status": 1, 
  "createdAt": -1 
}, { background: true });

// Geospatial index for delivery
db.orders.createIndex({ "deliveryAddress.location": "2dsphere" }, { background: true });

// Products collection indexes
db.products.createIndex({ "category": 1, "price": 1 }, { background: true });
db.products.createIndex({ "sku": 1 }, { unique: true, background: true });
db.products.createIndex({ "tags": 1 }, { background: true });
db.products.createIndex({ "price": 1, "rating": -1 }, { background: true });

// Text search for products
db.products.createIndex({
  "name": "text",
  "description": "text",
  "tags": "text"
}, {
  name: "product_text_search",
  weights: {
    "name": 10,
    "tags": 5,
    "description": 1
  },
  background: true
});

// Time-series data indexes (events, logs, metrics)
db.events.createIndex({ "timestamp": 1 }, { background: true });
db.events.createIndex({ "userId": 1, "timestamp": -1 }, { background: true });
db.events.createIndex({ "eventType": 1, "timestamp": -1 }, { background: true });

// TTL index for temporary data
db.sessions.createIndex({ "expiresAt": 1 }, { expireAfterSeconds: 0, background: true });
db.temporaryTokens.createIndex({ "createdAt": 1 }, { expireAfterSeconds: 3600, background: true });

// Partial indexes for specific conditions
db.users.createIndex(
  { "premium.subscriptionId": 1 },
  { 
    partialFilterExpression: { "premium.isActive": true },
    background: true
  }
);

db.orders.createIndex(
  { "paymentMethod": 1 },
  {
    partialFilterExpression: { "status": { $in: ["pending", "processing"] } },
    background: true
  }
);

// Analyze index usage and performance
function analyzeIndexUsage(collection) {
  print("=== Index Usage Analysis for " + collection + " ===");
  
  var stats = db[collection].aggregate([
    { $indexStats: {} }
  ]).toArray();
  
  stats.forEach(function(indexStat) {
    print("Index: " + indexStat.name);
    print("Usage: " + indexStat.accesses.ops + " operations");
    print("Since: " + indexStat.accesses.since);
    print("---");
  });
}

// Check index usage for all collections
["users", "orders", "products", "events"].forEach(analyzeIndexUsage);

// Monitor slow queries
db.setProfilingLevel(2, { slowms: 100, sampleRate: 0.1 });

// Query to find slow operations
db.system.profile.find({
  "ts": {
    $gte: new Date(Date.now() - 1000 * 60 * 60) // Last hour
  }
}).sort({ ts: -1 }).limit(10).pretty();

Aggregation Pipeline Optimization

// aggregation-optimization.js - Optimized aggregation queries
use myapp;

// User analytics aggregation with optimization
function getUserAnalytics(startDate, endDate) {
  return db.users.aggregate([
    // Early filtering to reduce document set
    {
      $match: {
        createdAt: { $gte: startDate, $lte: endDate },
        status: { $ne: "deleted" }
      }
    },
    
    // Project only needed fields early
    {
      $project: {
        _id: 1,
        email: 1,
        createdAt: 1,
        lastLogin: 1,
        "location.country": 1,
        "profile.age": 1,
        premium: 1
      }
    },
    
    // Add computed fields
    {
      $addFields: {
        registrationMonth: { $dateToString: { format: "%Y-%m", date: "$createdAt" } },
        daysSinceRegistration: {
          $divide: [
            { $subtract: [new Date(), "$createdAt"] },
            1000 * 60 * 60 * 24
          ]
        },
        isActive: {
          $cond: {
            if: { $gte: ["$lastLogin", new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)] },
            then: true,
            else: false
          }
        }
      }
    },
    
    // Group by month and country
    {
      $group: {
        _id: {
          month: "$registrationMonth",
          country: "$location.country"
        },
        totalUsers: { $sum: 1 },
        activeUsers: { $sum: { $cond: ["$isActive", 1, 0] } },
        premiumUsers: { $sum: { $cond: ["$premium.isActive", 1, 0] } },
        avgAge: { $avg: "$profile.age" },
        avgDaysSinceRegistration: { $avg: "$daysSinceRegistration" }
      }
    },
    
    // Sort results
    {
      $sort: { "_id.month": -1, "_id.country": 1 }
    },
    
    // Add activity rate calculation
    {
      $addFields: {
        activityRate: { 
          $multiply: [
            { $divide: ["$activeUsers", "$totalUsers"] },
            100
          ]
        }
      }
    }
  ], {
    allowDiskUse: true,
    cursor: { batchSize: 1000 }
  });
}

// Product recommendation aggregation
function getProductRecommendations(userId, limit = 10) {
  return db.orders.aggregate([
    // Find users with similar purchase history
    {
      $match: { userId: ObjectId(userId) }
    },
    {
      $unwind: "$items"
    },
    {
      $group: {
        _id: "$items.productId",
        purchaseCount: { $sum: 1 }
      }
    },
    {
      $sort: { purchaseCount: -1 }
    },
    {
      $limit: 5
    },
    
    // Find other users who bought these products
    {
      $lookup: {
        from: "orders",
        let: { productId: "$_id" },
        pipeline: [
          {
            $match: {
              $expr: {
                $and: [
                  { $in: ["$$productId", "$items.productId"] },
                  { $ne: ["$userId", ObjectId(userId)] }
                ]
              }
            }
          },
          { $group: { _id: "$userId" } }
        ],
        as: "similarUsers"
      }
    },
    
    // Get products bought by similar users
    {
      $lookup: {
        from: "orders", 
        let: { userIds: "$similarUsers._id" },
        pipeline: [
          {
            $match: {
              $expr: { $in: ["$userId", "$$userIds"] }
            }
          },
          { $unwind: "$items" },
          {
            $group: {
              _id: "$items.productId",
              score: { $sum: 1 }
            }
          },
          { $sort: { score: -1 } }
        ],
        as: "recommendations"
      }
    },
    
    // Flatten and get product details
    {
      $unwind: "$recommendations"
    },
    {
      $lookup: {
        from: "products",
        localField: "recommendations._id",
        foreignField: "_id", 
        as: "product"
      }
    },
    {
      $unwind: "$product"
    },
    
    // Final scoring and sorting
    {
      $project: {
        _id: "$product._id",
        name: "$product.name",
        price: "$product.price",
        rating: "$product.rating",
        score: "$recommendations.score"
      }
    },
    {
      $sort: { score: -1, rating: -1 }
    },
    {
      $limit: limit
    }
  ], {
    allowDiskUse: true
  });
}

// Real-time dashboard aggregation
function getDashboardMetrics(timeRange = "24h") {
  const startTime = new Date(Date.now() - parseTimeRange(timeRange));
  
  return db.events.aggregate([
    {
      $match: {
        timestamp: { $gte: startTime },
        eventType: { $in: ["page_view", "purchase", "signup", "login"] }
      }
    },
    
    // Time-based bucketing
    {
      $bucket: {
        groupBy: "$timestamp",
        boundaries: generateTimeBoundaries(startTime, new Date(), "1h"),
        default: "other",
        output: {
          pageViews: { 
            $sum: { $cond: [{ $eq: ["$eventType", "page_view"] }, 1, 0] }
          },
          purchases: {
            $sum: { $cond: [{ $eq: ["$eventType", "purchase"] }, 1, 0] }
          },
          signups: {
            $sum: { $cond: [{ $eq: ["$eventType", "signup"] }, 1, 0] }
          },
          logins: {
            $sum: { $cond: [{ $eq: ["$eventType", "login"] }, 1, 0] }
          },
          revenue: {
            $sum: { 
              $cond: [
                { $eq: ["$eventType", "purchase"] },
                "$metadata.amount",
                0
              ]
            }
          }
        }
      }
    },
    
    {
      $sort: { _id: 1 }
    }
  ], {
    allowDiskUse: true
  });
}

// Helper functions
function parseTimeRange(timeRange) {
  const units = { 'h': 3600000, 'd': 86400000, 'w': 604800000 };
  const match = timeRange.match(/^(\d+)([hdw])$/);
  return match ? parseInt(match[1]) * units[match[2]] : 86400000;
}

function generateTimeBoundaries(start, end, interval) {
  const boundaries = [];
  const intervalMs = parseTimeRange(interval);
  
  for (let time = start.getTime(); time <= end.getTime(); time += intervalMs) {
    boundaries.push(new Date(time));
  }
  
  return boundaries;
}

// Index hints for complex aggregations
function optimizeAggregationQuery() {
  // Use index hints to force optimal index usage
  return db.orders.aggregate([
    {
      $match: {
        createdAt: { $gte: new Date("2024-01-01") }
      }
    }
  ], {
    hint: { createdAt: -1 }
  });
}

Monitoring and Alerting

MongoDB Monitoring Setup

// monitoring-setup.js - Comprehensive monitoring configuration
use admin;

// Enable free monitoring (MongoDB 4.0+)
db.enableFreeMonitoring();

// Database statistics monitoring
function collectDatabaseStats() {
  const stats = {
    timestamp: new Date(),
    serverStatus: db.serverStatus(),
    dbStats: {},
    replSetStatus: null,
    shardingStatus: null
  };
  
  // Collect database statistics
  db.adminCommand("listDatabases").databases.forEach(function(dbInfo) {
    if (dbInfo.name !== "local" && dbInfo.name !== "config") {
      stats.dbStats[dbInfo.name] = db.getSiblingDB(dbInfo.name).stats();
    }
  });
  
  // Replica set status
  try {
    stats.replSetStatus = rs.status();
  } catch (e) {
    print("Not running in replica set mode");
  }
  
  // Sharding status
  try {
    stats.shardingStatus = sh.status();
  } catch (e) {
    print("Sharding not enabled");
  }
  
  return stats;
}

// Performance metrics collection
function collectPerformanceMetrics() {
  return {
    timestamp: new Date(),
    currentOps: db.currentOp({
      $or: [
        { "active": true },
        { "secs_running": { $gte: 5 } }
      ]
    }),
    slowQueries: db.system.profile.find({
      "ts": { $gte: new Date(Date.now() - 300000) }, // Last 5 minutes
      "millis": { $gte: 100 }
    }).sort({ ts: -1 }).limit(20).toArray(),
    topCollections: db.runCommand({
      "top": 1
    })
  };
}

// Connection monitoring
function monitorConnections() {
  const serverStatus = db.serverStatus();
  const connections = serverStatus.connections;
  
  return {
    timestamp: new Date(),
    current: connections.current,
    available: connections.available,
    totalCreated: connections.totalCreated,
    utilization: (connections.current / (connections.current + connections.available)) * 100
  };
}

// Index usage analysis
function analyzeIndexEfficiency() {
  const databases = ["myapp"]; // Add your database names
  const analysis = {};
  
  databases.forEach(function(dbName) {
    const db_ref = db.getSiblingDB(dbName);
    analysis[dbName] = {};
    
    db_ref.getCollectionNames().forEach(function(collName) {
      const coll = db_ref[collName];
      
      // Get index stats
      const indexStats = coll.aggregate([{ $indexStats: {} }]).toArray();
      
      // Get collection stats
      const collStats = coll.stats();
      
      analysis[dbName][collName] = {
        indexes: indexStats,
        totalIndexSize: collStats.totalIndexSize,
        avgObjSize: collStats.avgObjSize,
        count: collStats.count
      };
    });
  });
  
  return analysis;
}

// Automated health check
function healthCheck() {
  const health = {
    timestamp: new Date(),
    status: "healthy",
    checks: {},
    alerts: []
  };
  
  try {
    // Check replica set health
    const rsStatus = rs.status();
    health.checks.replicaSet = {
      status: "ok",
      primary: rsStatus.members.find(m => m.stateStr === "PRIMARY")?.name,
      secondaries: rsStatus.members.filter(m => m.stateStr === "SECONDARY").length
    };
    
    if (rsStatus.members.filter(m => m.stateStr === "SECONDARY").length < 1) {
      health.alerts.push("Insufficient secondary replicas");
      health.status = "warning";
    }
  } catch (e) {
    health.checks.replicaSet = { status: "error", error: e.message };
  }
  
  // Check connections
  const connStats = monitorConnections();
  health.checks.connections = {
    status: connStats.utilization > 80 ? "warning" : "ok",
    utilization: connStats.utilization,
    current: connStats.current,
    available: connStats.available
  };
  
  if (connStats.utilization > 90) {
    health.alerts.push("High connection utilization");
    health.status = "critical";
  }
  
  // Check disk space
  const serverStatus = db.serverStatus();
  health.checks.memory = {
    status: "ok",
    resident: serverStatus.mem.resident,
    virtual: serverStatus.mem.virtual,
    mappedWithJournal: serverStatus.mem.mappedWithJournal
  };
  
  // Check for slow queries
  const slowQueries = db.system.profile.find({
    "ts": { $gte: new Date(Date.now() - 300000) },
    "millis": { $gte: 1000 }
  }).count();
  
  health.checks.performance = {
    status: slowQueries > 10 ? "warning" : "ok",
    slowQueriesLast5Min: slowQueries
  };
  
  return health;
}

// Store monitoring data
use monitoring;

// Create time series collections for metrics (MongoDB 5.0+)
db.createCollection("metrics", {
  timeseries: {
    timeField: "timestamp",
    metaField: "type",
    granularity: "minutes"
  }
});

db.createCollection("performance", {
  timeseries: {
    timeField: "timestamp", 
    metaField: "category",
    granularity: "minutes"
  }
});

// Schedule regular monitoring (use with cron or similar)
function scheduleMonitoring() {
  // This would be run by an external scheduler
  const dbStats = collectDatabaseStats();
  const perfMetrics = collectPerformanceMetrics();
  const healthStatus = healthCheck();
  
  // Store in time series collections
  db.metrics.insertOne({
    timestamp: new Date(),
    type: "database",
    data: dbStats
  });
  
  db.performance.insertOne({
    timestamp: new Date(),
    category: "queries",
    data: perfMetrics
  });
  
  db.health.insertOne(healthStatus);
  
  // Send alerts if needed
  if (healthStatus.status !== "healthy") {
    sendAlert(healthStatus);
  }
}

// Alert function (implement based on your notification system)
function sendAlert(healthStatus) {
  print("ALERT: MongoDB health status: " + healthStatus.status);
  print("Alerts: " + JSON.stringify(healthStatus.alerts));
  // Implement actual alerting (email, Slack, PagerDuty, etc.)
}

Backup and Recovery Strategies

Automated Backup System

#!/bin/bash
# mongodb-backup.sh - Comprehensive backup script

set -euo pipefail

# Configuration
MONGODB_HOST="${MONGODB_HOST:-localhost:27017}"
MONGODB_USER="${MONGODB_USER:-backup-user}"
MONGODB_PASSWORD="${MONGODB_PASSWORD:-}"
BACKUP_DIR="${BACKUP_DIR:-/data/mongodb-backups}"
RETENTION_DAYS="${RETENTION_DAYS:-30}"
S3_BUCKET="${S3_BUCKET:-mongodb-backups}"
DATABASES="${DATABASES:-myapp}"
ENCRYPTION_KEY="${ENCRYPTION_KEY:-}"

# Logging
LOG_FILE="${BACKUP_DIR}/backup.log"
mkdir -p "${BACKUP_DIR}"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "${LOG_FILE}"
}

# Error handling
cleanup() {
    local exit_code=$?
    if [ ${exit_code} -ne 0 ]; then
        log "ERROR: Backup failed with exit code ${exit_code}"
        send_alert "MongoDB backup failed" "Backup process failed with exit code ${exit_code}"
    fi
    exit ${exit_code}
}
trap cleanup EXIT

send_alert() {
    local subject=$1
    local message=$2
    
    # Implement your alerting mechanism here
    log "ALERT: ${subject} - ${message}"
    
    # Example: Send to Slack
    if [ -n "${SLACK_WEBHOOK_URL:-}" ]; then
        curl -X POST -H 'Content-type: application/json' \
            --data "{\"text\":\"${subject}: ${message}\"}" \
            "${SLACK_WEBHOOK_URL}"
    fi
}

# Backup functions
perform_logical_backup() {
    local database=$1
    local timestamp=$(date '+%Y%m%d_%H%M%S')
    local backup_path="${BACKUP_DIR}/${database}_${timestamp}"
    
    log "Starting logical backup for database: ${database}"
    
    # Create backup directory
    mkdir -p "${backup_path}"
    
    # Mongodump with compression and authentication
    mongodump \
        --host="${MONGODB_HOST}" \
        --username="${MONGODB_USER}" \
        --password="${MONGODB_PASSWORD}" \
        --authenticationDatabase=admin \
        --db="${database}" \
        --out="${backup_path}" \
        --gzip \
        --oplog \
        --numParallelCollections=4
    
    # Create archive
    tar -czf "${backup_path}.tar.gz" -C "${BACKUP_DIR}" "$(basename "${backup_path}")"
    
    # Encrypt if key provided
    if [ -n "${ENCRYPTION_KEY}" ]; then
        log "Encrypting backup archive"
        openssl enc -aes-256-cbc -salt -in "${backup_path}.tar.gz" \
            -out "${backup_path}.tar.gz.enc" -k "${ENCRYPTION_KEY}"
        rm "${backup_path}.tar.gz"
        backup_file="${backup_path}.tar.gz.enc"
    else
        backup_file="${backup_path}.tar.gz"
    fi
    
    # Calculate checksum
    sha256sum "${backup_file}" > "${backup_file}.sha256"
    
    # Cleanup uncompressed directory
    rm -rf "${backup_path}"
    
    log "Logical backup completed: ${backup_file}"
    echo "${backup_file}"
}

perform_physical_backup() {
    local timestamp=$(date '+%Y%m%d_%H%M%S')
    local snapshot_name="mongodb_snapshot_${timestamp}"
    
    log "Starting physical backup (filesystem snapshot)"
    
    # Stop writes (if acceptable for your use case)
    # mongo --host="${MONGODB_HOST}" --eval "db.fsyncLock()"
    
    # Create filesystem snapshot (example for LVM)
    if command -v lvcreate >/dev/null 2>&1; then
        lvcreate -L1G -s -n "${snapshot_name}" /dev/vg0/mongodb
        
        # Mount snapshot and copy data
        mkdir -p "/mnt/${snapshot_name}"
        mount "/dev/vg0/${snapshot_name}" "/mnt/${snapshot_name}"
        
        # Create archive from snapshot
        tar -czf "${BACKUP_DIR}/physical_${timestamp}.tar.gz" \
            -C "/mnt/${snapshot_name}" .
        
        # Cleanup
        umount "/mnt/${snapshot_name}"
        lvremove -f "/dev/vg0/${snapshot_name}"
        rmdir "/mnt/${snapshot_name}"
        
        log "Physical backup completed: physical_${timestamp}.tar.gz"
    else
        log "LVM not available, skipping physical backup"
    fi
    
    # Unlock writes
    # mongo --host="${MONGODB_HOST}" --eval "db.fsyncUnlock()"
}

upload_to_s3() {
    local backup_file=$1
    local s3_key="mongodb/$(basename "${backup_file}")"
    
    if command -v aws >/dev/null 2>&1; then
        log "Uploading to S3: ${s3_key}"
        
        aws s3 cp "${backup_file}" "s3://${S3_BUCKET}/${s3_key}" \
            --storage-class STANDARD_IA \
            --server-side-encryption AES256
        
        # Upload checksum
        aws s3 cp "${backup_file}.sha256" "s3://${S3_BUCKET}/${s3_key}.sha256"
        
        # Set lifecycle policy for automatic cleanup
        aws s3api put-object-tagging \
            --bucket "${S3_BUCKET}" \
            --key "${s3_key}" \
            --tagging "TagSet=[{Key=BackupType,Value=MongoDB},{Key=RetentionDays,Value=${RETENTION_DAYS}}]"
        
        log "Upload completed: ${s3_key}"
    else
        log "AWS CLI not available, skipping S3 upload"
    fi
}

cleanup_old_backups() {
    log "Cleaning up backups older than ${RETENTION_DAYS} days"
    
    # Local cleanup
    find "${BACKUP_DIR}" -name "*.tar.gz*" -mtime "+${RETENTION_DAYS}" -delete
    
    # S3 cleanup (if lifecycle policies not set)
    if command -v aws >/dev/null 2>&1; then
        aws s3 ls "s3://${S3_BUCKET}/mongodb/" --recursive | \
            awk '{print $4}' | \
            while read -r key; do
                aws s3api head-object --bucket "${S3_BUCKET}" --key "${key}" \
                    --query 'LastModified' --output text | \
                    xargs -I {} date -d {} +%s | \
                    awk -v cutoff="$(date -d "${RETENTION_DAYS} days ago" +%s)" \
                        -v key="${key}" \
                        '$1 < cutoff {print key}' | \
                    xargs -r -I {} aws s3 rm "s3://${S3_BUCKET}/{}"
            done
    fi
}

verify_backup() {
    local backup_file=$1
    
    log "Verifying backup integrity: ${backup_file}"
    
    # Verify checksum
    if sha256sum -c "${backup_file}.sha256"; then
        log "Checksum verification passed"
    else
        log "ERROR: Checksum verification failed"
        return 1
    fi
    
    # Test restore (to temporary location)
    local test_dir="/tmp/backup_verify_$(date +%s)"
    mkdir -p "${test_dir}"
    
    if [[ "${backup_file}" == *.enc ]]; then
        # Decrypt and extract
        openssl enc -aes-256-cbc -d -in "${backup_file}" \
            -out "${test_dir}/backup.tar.gz" -k "${ENCRYPTION_KEY}"
        tar -xzf "${test_dir}/backup.tar.gz" -C "${test_dir}"
    else
        # Extract directly
        tar -xzf "${backup_file}" -C "${test_dir}"
    fi
    
    # Verify MongoDB can read the backup
    if mongorestore --host="${MONGODB_HOST}" \
            --username="${MONGODB_USER}" \
            --password="${MONGODB_PASSWORD}" \
            --authenticationDatabase=admin \
            --db="test_restore_$$" \
            --dir="${test_dir}" \
            --dryRun; then
        log "Backup verification successful"
        # Cleanup test database
        mongo --host="${MONGODB_HOST}" \
            --username="${MONGODB_USER}" \
            --password="${MONGODB_PASSWORD}" \
            --authenticationDatabase=admin \
            --eval "db.getSiblingDB('test_restore_$$').dropDatabase()"
    else
        log "ERROR: Backup verification failed"
        return 1
    fi
    
    # Cleanup
    rm -rf "${test_dir}"
}

# Point-in-time recovery setup
setup_oplog_backup() {
    log "Setting up continuous oplog backup"
    
    # Create oplog backup script
    cat > "${BACKUP_DIR}/oplog-backup.sh" << 'EOF'
#!/bin/bash
OPLOG_DIR="${BACKUP_DIR}/oplog"
mkdir -p "${OPLOG_DIR}"

while true; do
    timestamp=$(date '+%Y%m%d_%H%M%S')
    mongodump \
        --host="${MONGODB_HOST}" \
        --username="${MONGODB_USER}" \
        --password="${MONGODB_PASSWORD}" \
        --authenticationDatabase=admin \
        --db=local \
        --collection=oplog.rs \
        --out="${OPLOG_DIR}/oplog_${timestamp}" \
        --gzip
    
    # Upload to S3
    tar -czf "${OPLOG_DIR}/oplog_${timestamp}.tar.gz" \
        -C "${OPLOG_DIR}" "oplog_${timestamp}"
    
    aws s3 cp "${OPLOG_DIR}/oplog_${timestamp}.tar.gz" \
        "s3://${S3_BUCKET}/oplog/oplog_${timestamp}.tar.gz"
    
    # Cleanup local oplog files older than 1 day
    find "${OPLOG_DIR}" -name "oplog_*" -mtime +1 -delete
    
    sleep 3600  # Run every hour
done
EOF
    
    chmod +x "${BACKUP_DIR}/oplog-backup.sh"
    log "Oplog backup script created at ${BACKUP_DIR}/oplog-backup.sh"
}

# Main backup execution
main() {
    log "Starting MongoDB backup process"
    
    # Perform backups for each database
    for db in ${DATABASES//,/ }; do
        backup_file=$(perform_logical_backup "${db}")
        verify_backup "${backup_file}"
        upload_to_s3 "${backup_file}"
    done
    
    # Physical backup (if enabled)
    if [ "${ENABLE_PHYSICAL_BACKUP:-false}" = "true" ]; then
        perform_physical_backup
    fi
    
    # Setup oplog backup for PITR
    if [ "${ENABLE_OPLOG_BACKUP:-false}" = "true" ]; then
        setup_oplog_backup
    fi
    
    # Cleanup old backups
    cleanup_old_backups
    
    log "MongoDB backup process completed successfully"
}

# Execute main function
main "$@"

Recovery Procedures

#!/bin/bash
# mongodb-restore.sh - Comprehensive restore script

set -euo pipefail

# Configuration
MONGODB_HOST="${MONGODB_HOST:-localhost:27017}"
MONGODB_USER="${MONGODB_USER:-admin}"
MONGODB_PASSWORD="${MONGODB_PASSWORD:-}"
BACKUP_DIR="${BACKUP_DIR:-/data/mongodb-backups}"
S3_BUCKET="${S3_BUCKET:-mongodb-backups}"
ENCRYPTION_KEY="${ENCRYPTION_KEY:-}"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

download_from_s3() {
    local s3_key=$1
    local local_file=$2
    
    log "Downloading from S3: ${s3_key}"
    
    aws s3 cp "s3://${S3_BUCKET}/${s3_key}" "${local_file}"
    aws s3 cp "s3://${S3_BUCKET}/${s3_key}.sha256" "${local_file}.sha256"
    
    # Verify checksum
    if sha256sum -c "${local_file}.sha256"; then
        log "Download verification successful"
    else
        log "ERROR: Downloaded file checksum verification failed"
        exit 1
    fi
}

restore_database() {
    local backup_file=$1
    local target_db=$2
    local restore_dir="/tmp/restore_$(date +%s)"
    
    log "Starting database restore from: ${backup_file}"
    
    mkdir -p "${restore_dir}"
    
    # Decrypt and extract if needed
    if [[ "${backup_file}" == *.enc ]]; then
        log "Decrypting backup file"
        openssl enc -aes-256-cbc -d -in "${backup_file}" \
            -out "${restore_dir}/backup.tar.gz" -k "${ENCRYPTION_KEY}"
        tar -xzf "${restore_dir}/backup.tar.gz" -C "${restore_dir}"
    else
        tar -xzf "${backup_file}" -C "${restore_dir}"
    fi
    
    # Find the database directory
    db_dir=$(find "${restore_dir}" -type d -name "*" | head -1)
    
    # Perform restore
    log "Restoring database: ${target_db}"
    
    mongorestore \
        --host="${MONGODB_HOST}" \
        --username="${MONGODB_USER}" \
        --password="${MONGODB_PASSWORD}" \
        --authenticationDatabase=admin \
        --db="${target_db}" \
        --dir="${db_dir}/${target_db}" \
        --gzip \
        --drop \
        --numParallelCollections=4 \
        --numInsertionWorkersPerCollection=2
    
    # Cleanup
    rm -rf "${restore_dir}"
    
    log "Database restore completed: ${target_db}"
}

point_in_time_recovery() {
    local backup_date=$1
    local target_timestamp=$2
    local target_db=$3
    
    log "Starting point-in-time recovery to: ${target_timestamp}"
    
    # First restore from base backup
    base_backup=$(find "${BACKUP_DIR}" -name "*${backup_date}*.tar.gz" | head -1)
    if [ -z "${base_backup}" ]; then
        log "ERROR: Base backup not found for date: ${backup_date}"
        exit 1
    fi
    
    restore_database "${base_backup}" "${target_db}"
    
    # Apply oplog entries up to target timestamp
    log "Applying oplog entries up to: ${target_timestamp}"
    
    # Download and apply oplog files
    local oplog_dir="/tmp/oplog_recovery_$(date +%s)"
    mkdir -p "${oplog_dir}"
    
    # Find relevant oplog files from S3
    aws s3 ls "s3://${S3_BUCKET}/oplog/" | \
        grep -E "oplog_[0-9]+_[0-9]+\.tar\.gz$" | \
        while read -r line; do
            oplog_file=$(echo "${line}" | awk '{print $4}')
            oplog_date=$(echo "${oplog_file}" | sed -E 's/oplog_([0-9]{8})_[0-9]+\.tar\.gz/\1/')
            
            if [[ "${oplog_date}" -ge "${backup_date}" ]] && \
               [[ "${oplog_date}" -le "$(date -d "${target_timestamp}" +%Y%m%d)" ]]; then
                
                aws s3 cp "s3://${S3_BUCKET}/oplog/${oplog_file}" \
                    "${oplog_dir}/${oplog_file}"
                
                # Extract and apply
                tar -xzf "${oplog_dir}/${oplog_file}" -C "${oplog_dir}"
                
                mongorestore \
                    --host="${MONGODB_HOST}" \
                    --username="${MONGODB_USER}" \
                    --password="${MONGODB_PASSWORD}" \
                    --authenticationDatabase=admin \
                    --oplogReplay \
                    --oplogLimit="$(date -d "${target_timestamp}" +%s):1" \
                    --dir="${oplog_dir}"
            fi
        done
    
    # Cleanup
    rm -rf "${oplog_dir}"
    
    log "Point-in-time recovery completed"
}

# Interactive restore menu
show_menu() {
    echo "MongoDB Restore Options:"
    echo "1. List available backups"
    echo "2. Restore latest backup"
    echo "3. Restore specific backup"
    echo "4. Point-in-time recovery" 
    echo "5. Download backup from S3"
    echo "6. Exit"
}

list_backups() {
    echo "Local backups:"
    find "${BACKUP_DIR}" -name "*.tar.gz*" -type f | sort -r | head -10
    
    echo ""
    echo "S3 backups:"
    aws s3 ls "s3://${S3_BUCKET}/mongodb/" --recursive | head -10
}

main() {
    while true; do
        show_menu
        read -p "Enter your choice (1-6): " choice
        
        case $choice in
            1)
                list_backups
                ;;
            2)
                latest_backup=$(find "${BACKUP_DIR}" -name "*.tar.gz" -type f | sort -r | head -1)
                if [ -n "${latest_backup}" ]; then
                    read -p "Enter target database name: " target_db
                    restore_database "${latest_backup}" "${target_db}"
                else
                    echo "No local backups found"
                fi
                ;;
            3)
                read -p "Enter backup file path: " backup_path
                read -p "Enter target database name: " target_db
                if [ -f "${backup_path}" ]; then
                    restore_database "${backup_path}" "${target_db}"
                else
                    echo "Backup file not found: ${backup_path}"
                fi
                ;;
            4)
                read -p "Enter backup date (YYYYMMDD): " backup_date
                read -p "Enter target timestamp (YYYY-MM-DD HH:MM:SS): " target_timestamp
                read -p "Enter target database name: " target_db
                point_in_time_recovery "${backup_date}" "${target_timestamp}" "${target_db}"
                ;;
            5)
                read -p "Enter S3 key (mongodb/filename.tar.gz): " s3_key
                read -p "Enter local file path: " local_path
                download_from_s3 "${s3_key}" "${local_path}"
                ;;
            6)
                echo "Exiting..."
                exit 0
                ;;
            *)
                echo "Invalid choice. Please try again."
                ;;
        esac
        
        echo ""
        read -p "Press Enter to continue..."
        echo ""
    done
}

# Run interactive menu if no arguments provided
if [ $# -eq 0 ]; then
    main
else
    # Command line usage
    case $1 in
        restore)
            restore_database "$2" "$3"
            ;;
        pitr)
            point_in_time_recovery "$2" "$3" "$4"
            ;;
        list)
            list_backups
            ;;
        *)
            echo "Usage: $0 [restore|pitr|list] [args...]"
            exit 1
            ;;
    esac
fi

Container Deployment

Docker Configuration for MongoDB

# Dockerfile.mongodb - Custom MongoDB container
FROM mongo:7.0-jammy

# Install additional tools
RUN apt-get update && apt-get install -y \
    curl \
    netcat \
    procps \
    && rm -rf /var/lib/apt/lists/*

# Create directories for data and configuration
RUN mkdir -p /data/db /data/configdb /var/log/mongodb

# Copy configuration files
COPY mongod.conf /etc/mongod.conf
COPY docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/

# Health check script
COPY healthcheck.sh /usr/local/bin/healthcheck.sh
RUN chmod +x /usr/local/bin/healthcheck.sh

# Set proper permissions
RUN chown -R mongodb:mongodb /data /var/log/mongodb

EXPOSE 27017

HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
    CMD /usr/local/bin/healthcheck.sh

USER mongodb

CMD ["mongod", "--config", "/etc/mongod.conf"]
#!/bin/bash
# healthcheck.sh - MongoDB health check script

# Check if MongoDB is responding
mongo_status=$(mongosh --quiet --eval "db.runCommand('ping').ok" 2>/dev/null || echo "0")

if [ "$mongo_status" = "1" ]; then
    # Additional checks for replica set
    if [ -n "$REPLICA_SET_NAME" ]; then
        rs_status=$(mongosh --quiet --eval "
            try {
                var status = rs.status();
                var healthy_members = status.members.filter(m => 
                    m.health === 1 && 
                    ['PRIMARY', 'SECONDARY', 'ARBITER'].includes(m.stateStr)
                ).length;
                print(healthy_members >= 2 ? '1' : '0');
            } catch (e) {
                print('0');
            }
        " 2>/dev/null || echo "0")
        
        if [ "$rs_status" = "1" ]; then
            exit 0
        else
            echo "Replica set not healthy"
            exit 1
        fi
    else
        exit 0
    fi
else
    echo "MongoDB not responding"
    exit 1
fi

Docker Compose for Production

version: '3.8'

services:
  mongo-primary:
    build:
      context: .
      dockerfile: Dockerfile.mongodb
    restart: unless-stopped
    hostname: mongo-primary
    environment:
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_ROOT_USER}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_ROOT_PASS}
      - REPLICA_SET_NAME=myapp-rs
    ports:
      - "27017:27017"
    volumes:
      - mongo_primary_data:/data/db
      - mongo_primary_config:/data/configdb
      - mongo_logs:/var/log/mongodb
      - ./keyfile:/data/keyfile:ro
    networks:
      - mongo-cluster
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: '2.0'
        reservations:
          memory: 2G
          cpus: '1.0'
    command: >
      mongod 
      --replSet myapp-rs
      --keyFile /data/keyfile
      --bind_ip_all
      --auth

  mongo-secondary1:
    build:
      context: .
      dockerfile: Dockerfile.mongodb
    restart: unless-stopped
    hostname: mongo-secondary1
    environment:
      - REPLICA_SET_NAME=myapp-rs
    ports:
      - "27018:27017"
    volumes:
      - mongo_secondary1_data:/data/db
      - mongo_secondary1_config:/data/configdb
      - ./keyfile:/data/keyfile:ro
    networks:
      - mongo-cluster
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: '2.0'
        reservations:
          memory: 2G
          cpus: '1.0'
    command: >
      mongod 
      --replSet myapp-rs
      --keyFile /data/keyfile
      --bind_ip_all
      --auth
    depends_on:
      - mongo-primary

  mongo-secondary2:
    build:
      context: .
      dockerfile: Dockerfile.mongodb
    restart: unless-stopped
    hostname: mongo-secondary2
    environment:
      - REPLICA_SET_NAME=myapp-rs
    ports:
      - "27019:27017"
    volumes:
      - mongo_secondary2_data:/data/db
      - mongo_secondary2_config:/data/configdb
      - ./keyfile:/data/keyfile:ro
    networks:
      - mongo-cluster
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: '2.0'
        reservations:
          memory: 2G
          cpus: '1.0'
    command: >
      mongod 
      --replSet myapp-rs
      --keyFile /data/keyfile
      --bind_ip_all
      --auth
    depends_on:
      - mongo-primary

  mongo-express:
    image: mongo-express:latest
    restart: unless-stopped
    environment:
      - ME_CONFIG_MONGODB_SERVER=mongo-primary
      - ME_CONFIG_MONGODB_PORT=27017
      - ME_CONFIG_MONGODB_ADMINUSERNAME=${MONGO_ROOT_USER}
      - ME_CONFIG_MONGODB_ADMINPASSWORD=${MONGO_ROOT_PASS}
      - ME_CONFIG_BASICAUTH_USERNAME=${MONGO_EXPRESS_USER}
      - ME_CONFIG_BASICAUTH_PASSWORD=${MONGO_EXPRESS_PASS}
    ports:
      - "8081:8081"
    networks:
      - mongo-cluster
    depends_on:
      - mongo-primary

  mongodb-backup:
    build:
      context: .
      dockerfile: Dockerfile.backup
    restart: unless-stopped
    environment:
      - MONGODB_HOST=mongo-primary:27017
      - MONGODB_USER=${BACKUP_USER}
      - MONGODB_PASSWORD=${BACKUP_PASS}
      - S3_BUCKET=${S3_BUCKET}
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - BACKUP_SCHEDULE=0 2 * * *
    volumes:
      - backup_data:/data/backups
    networks:
      - mongo-cluster
    depends_on:
      - mongo-primary

volumes:
  mongo_primary_data:
    driver: local
  mongo_primary_config:
    driver: local
  mongo_secondary1_data:
    driver: local
  mongo_secondary1_config:
    driver: local
  mongo_secondary2_data:
    driver: local
  mongo_secondary2_config:
    driver: local
  mongo_logs:
    driver: local
  backup_data:
    driver: local

networks:
  mongo-cluster:
    driver: bridge
    ipam:
      config:
        - subnet: 172.25.0.0/16

Ubuntu Server Installation and Setup

Installing MongoDB on Ubuntu 22.04/24.04

#!/bin/bash
# mongodb-ubuntu-install.sh - Complete MongoDB setup on Ubuntu

# Update system packages
sudo apt update && sudo apt upgrade -y

# Import MongoDB public GPG key
wget -qO - https://www.mongodb.org/static/pgp/server-7.0.asc | sudo apt-key add -

# Add MongoDB repository
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list

# Update package database
sudo apt update

# Install MongoDB Community Edition
sudo apt install -y mongodb-org mongodb-org-tools

# Install additional utilities
sudo apt install -y htop iotop sysstat

# Start and enable MongoDB
sudo systemctl start mongod
sudo systemctl enable mongod

# Configure firewall
sudo ufw allow 27017/tcp

# Create backup directories
sudo mkdir -p /var/lib/mongodb/backups
sudo mkdir -p /var/lib/mongodb/logs
sudo chown -R mongodb:mongodb /var/lib/mongodb/backups
sudo chown -R mongodb:mongodb /var/lib/mongodb/logs

Production System Configuration

#!/bin/bash
# system-tuning.sh - Optimize Ubuntu for MongoDB

# Kernel parameters for MongoDB
cat >> /etc/sysctl.conf << EOF
# MongoDB optimization
vm.swappiness = 1
vm.dirty_background_ratio = 5
vm.dirty_ratio = 15
vm.max_map_count = 262144

# Network optimization
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
net.ipv4.tcp_keepalive_time = 300
net.core.netdev_max_backlog = 5000
EOF

# Apply kernel parameters
sudo sysctl -p

# Disable transparent hugepages (critical for MongoDB)
echo 'never' | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo 'never' | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

# Make persistent
cat > /etc/systemd/system/disable-thp.service << EOF
[Unit]
Description=Disable Transparent Huge Pages (THP)
DefaultDependencies=no
After=sysinit.target local-fs.target
Before=mongod.service

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never | tee /sys/kernel/mm/transparent_hugepage/enabled > /dev/null'
ExecStart=/bin/sh -c 'echo never | tee /sys/kernel/mm/transparent_hugepage/defrag > /dev/null'

[Install]
WantedBy=basic.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable disable-thp
sudo systemctl start disable-thp

# Configure limits
cat >> /etc/security/limits.conf << EOF
mongodb soft nofile 64000
mongodb hard nofile 64000
mongodb soft nproc 32000
mongodb hard nproc 32000
EOF

# Configure systemd limits for MongoDB
sudo mkdir -p /etc/systemd/system/mongod.service.d/
cat > /etc/systemd/system/mongod.service.d/limits.conf << EOF
[Service]
LimitFSIZE=infinity
LimitCPU=infinity
LimitAS=infinity
LimitNOFILE=64000
LimitRSS=infinity
LimitNPROC=32000
EOF

# Install and configure NTP for time synchronization
sudo apt install -y ntp
sudo systemctl enable ntp
sudo systemctl start ntp

sudo systemctl daemon-reload
sudo systemctl restart mongod

Database Setup and Security Hardening

#!/bin/bash
# database-setup.sh - Create databases and users with proper security

# Enable authentication
sudo systemctl stop mongod

# Add authentication to MongoDB config
cat >> /etc/mongod.conf << EOF
security:
  authorization: enabled
EOF

sudo systemctl start mongod

# Create administrative user
mongosh --eval "
use admin;
db.createUser({
  user: 'admin',
  pwd: 'admin_secure_password',
  roles: [
    { role: 'userAdminAnyDatabase', db: 'admin' },
    { role: 'readWriteAnyDatabase', db: 'admin' },
    { role: 'dbAdminAnyDatabase', db: 'admin' },
    { role: 'clusterAdmin', db: 'admin' }
  ]
});
"

# Create application database and user
mongosh -u admin -p admin_secure_password --authenticationDatabase admin --eval "
use myapp;
db.createUser({
  user: 'app_user',
  pwd: 'app_secure_password',
  roles: [
    { role: 'readWrite', db: 'myapp' }
  ]
});

// Create read-only user
db.createUser({
  user: 'readonly_user',
  pwd: 'readonly_secure_password',
  roles: [
    { role: 'read', db: 'myapp' }
  ]
});

// Create monitoring user
use admin;
db.createUser({
  user: 'monitoring',
  pwd: 'monitoring_secure_password',
  roles: [
    { role: 'clusterMonitor', db: 'admin' },
    { role: 'read', db: 'local' }
  ]
});
"

# Configure network security
cat >> /etc/mongod.conf << EOF
net:
  bindIp: 127.0.0.1,mongodb.example.com
  port: 27017
  maxIncomingConnections: 1000

# Enable profiling for slow queries
operationProfiling:
  mode: slowOp
  slowOpThresholdMs: 100
  slowOpSampleRate: 0.02
EOF

sudo systemctl restart mongod

SSL/TLS Configuration

#!/bin/bash
# ssl-setup.sh - Configure SSL/TLS for MongoDB

# Create SSL directory
sudo mkdir -p /etc/ssl/mongodb
cd /etc/ssl/mongodb

# Generate CA private key
sudo openssl genrsa -out ca-key.pem 4096

# Generate CA certificate
sudo openssl req -new -x509 -days 3650 -key ca-key.pem -out ca.pem \
  -subj "/C=US/ST=State/L=City/O=Organization/CN=MongoDB-CA"

# Generate server private key
sudo openssl genrsa -out server-key.pem 4096

# Create certificate signing request
sudo openssl req -new -key server-key.pem -out server.csr \
  -subj "/C=US/ST=State/L=City/O=Organization/CN=mongodb.example.com"

# Sign server certificate
sudo openssl x509 -req -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out server.pem -days 365

# Combine server certificate and key
sudo cat server.pem server-key.pem > server-combined.pem

# Generate client certificates
sudo openssl genrsa -out client-key.pem 4096
sudo openssl req -new -key client-key.pem -out client.csr \
  -subj "/C=US/ST=State/L=City/O=Organization/CN=mongodb-client"
sudo openssl x509 -req -in client.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out client.pem -days 365
sudo cat client.pem client-key.pem > client-combined.pem

# Set proper permissions
sudo chown mongodb:mongodb /etc/ssl/mongodb/*
sudo chmod 600 /etc/ssl/mongodb/*-key.pem
sudo chmod 644 /etc/ssl/mongodb/*.pem

# Update MongoDB configuration for SSL
cat >> /etc/mongod.conf << EOF
net:
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/ssl/mongodb/server-combined.pem
    CAFile: /etc/ssl/mongodb/ca.pem
    allowConnectionsWithoutCertificates: false
EOF

# Clean up temporary files
sudo rm -f server.csr client.csr

sudo systemctl restart mongod

# Create connection test script
cat > /usr/local/bin/test-mongodb-ssl.sh << 'EOF'
#!/bin/bash
# Test MongoDB SSL connection
mongosh --tls \
        --tlsCertificateKeyFile /etc/ssl/mongodb/client-combined.pem \
        --tlsCAFile /etc/ssl/mongodb/ca.pem \
        --host mongodb.example.com:27017 \
        -u admin -p admin_secure_password \
        --authenticationDatabase admin \
        --eval "db.runCommand('hello')"
EOF

chmod +x /usr/local/bin/test-mongodb-ssl.sh

Automated Monitoring and Alerts

#!/bin/bash
# monitoring-setup.sh - Set up MongoDB monitoring on Ubuntu

# Install MongoDB exporter for Prometheus
wget https://github.com/percona/mongodb_exporter/releases/download/v0.40.0/mongodb_exporter-0.40.0.linux-amd64.tar.gz
tar -xzf mongodb_exporter-0.40.0.linux-amd64.tar.gz
sudo mv mongodb_exporter-0.40.0.linux-amd64/mongodb_exporter /usr/local/bin/
rm -rf mongodb_exporter-*

# Create mongodb_exporter user
sudo useradd --system --shell /bin/false mongodb_exporter

# Create systemd service
cat > /etc/systemd/system/mongodb_exporter.service << EOF
[Unit]
Description=MongoDB Prometheus Exporter
After=network.target

[Service]
Type=simple
User=mongodb_exporter
Group=mongodb_exporter
ExecStart=/usr/local/bin/mongodb_exporter \\
    --mongodb.uri=mongodb://monitoring:monitoring_secure_password@localhost:27017/admin?authSource=admin \\
    --web.listen-address=:9216 \\
    --collect-all
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable mongodb_exporter
sudo systemctl start mongodb_exporter

# Create health check script
cat > /usr/local/bin/mongodb-health-check.sh << 'EOF'
#!/bin/bash
# MongoDB health monitoring script

LOGFILE="/var/log/mongodb/health-check.log"
EMAIL="admin@example.com"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOGFILE
}

check_mongodb_status() {
    if ! systemctl is-active --quiet mongod; then
        log "CRITICAL: MongoDB service is not running"
        echo "MongoDB service is down" | mail -s "MongoDB Critical Alert" $EMAIL
        return 1
    fi
}

check_connections() {
    local conn_count=$(mongosh --quiet --eval "db.serverStatus().connections.current" 2>/dev/null || echo "0")
    local max_conn=$(mongosh --quiet --eval "db.serverStatus().connections.available + db.serverStatus().connections.current" 2>/dev/null || echo "1000")
    local usage=$((conn_count * 100 / max_conn))
    
    if [ $usage -gt 90 ]; then
        log "CRITICAL: Connection usage at ${usage}% (${conn_count}/${max_conn})"
        echo "MongoDB connection usage critical: ${usage}%" | mail -s "MongoDB Connection Alert" $EMAIL
    elif [ $usage -gt 80 ]; then
        log "WARNING: Connection usage at ${usage}% (${conn_count}/${max_conn})"
    fi
}

check_replica_set() {
    local rs_status=$(mongosh --quiet --eval "rs.status()" 2>/dev/null | grep -c '"health" : 1' || echo "0")
    
    if [ $rs_status -lt 2 ]; then
        log "CRITICAL: Replica set member health issue"
        echo "MongoDB replica set has unhealthy members" | mail -s "MongoDB Replica Set Alert" $EMAIL
    fi
}

check_disk_space() {
    local usage=$(df /var/lib/mongodb | tail -1 | awk '{print $5}' | sed 's/%//')
    
    if [ $usage -gt 90 ]; then
        log "CRITICAL: Disk usage at ${usage}%"
        echo "MongoDB disk usage critical: ${usage}%" | mail -s "MongoDB Disk Alert" $EMAIL
    elif [ $usage -gt 80 ]; then
        log "WARNING: Disk usage at ${usage}%"
    fi
}

check_slow_queries() {
    local slow_count=$(mongosh --quiet --eval "
        db.system.profile.find({ts: {\$gte: new Date(Date.now() - 5*60*1000)}}).count()
    " 2>/dev/null || echo "0")
    
    if [ $slow_count -gt 10 ]; then
        log "WARNING: $slow_count slow queries in last 5 minutes"
        echo "MongoDB has $slow_count slow queries" | mail -s "MongoDB Performance Alert" $EMAIL
    fi
}

check_memory_usage() {
    local resident=$(mongosh --quiet --eval "db.serverStatus().mem.resident" 2>/dev/null || echo "0")
    local virtual=$(mongosh --quiet --eval "db.serverStatus().mem.virtual" 2>/dev/null || echo "0")
    local total_mem=$(free -m | grep '^Mem:' | awk '{print $2}')
    local usage=$((resident * 100 / total_mem))
    
    if [ $usage -gt 85 ]; then
        log "WARNING: High memory usage: ${usage}% (${resident}MB/${total_mem}MB)"
    fi
}

# Run checks
check_mongodb_status
if [ $? -eq 0 ]; then
    check_connections
    check_replica_set  
    check_disk_space
    check_slow_queries
    check_memory_usage
fi
EOF

chmod +x /usr/local/bin/mongodb-health-check.sh

# Add to crontab
(crontab -l 2>/dev/null; echo "*/5 * * * * /usr/local/bin/mongodb-health-check.sh") | crontab -

# Create maintenance script
cat > /usr/local/bin/mongodb-maintenance.sh << 'EOF'
#!/bin/bash
# MongoDB maintenance script

# Compact collections (run during low traffic)
mongosh --eval "
use myapp;
db.runCommand({compact: 'users'});
db.runCommand({compact: 'orders'});
db.runCommand({compact: 'products'});
"

# Update statistics
mongosh --eval "
db.runCommand({planCacheClear: 1});
"

# Log maintenance completion
echo "[$(date '+%Y-%m-%d %H:%M:%S')] MongoDB maintenance completed" >> /var/log/mongodb/maintenance.log
EOF

chmod +x /usr/local/bin/mongodb-maintenance.sh

# Weekly maintenance
(crontab -l 2>/dev/null; echo "0 3 * * 0 /usr/local/bin/mongodb-maintenance.sh") | crontab -

Performance Benchmarks

MongoDB Performance Metrics

MetricSingle Instance3-Member Replica SetSharded Cluster (3 shards)Notes
Writes/sec15,00012,00045,000Simple document inserts
Reads/sec50,000150,000200,000+With read from secondaries
Latency (p95)5ms8ms12msSingle document queries
Latency (p99)25ms35ms45msComplex aggregations
Storage Efficiency100%300%900%With compression
Memory Usage2GB6GB12GB100M documents
Network I/O100MB/s150MB/s400MB/sPeak throughput

Optimization Checklist

  • ✅ Configure appropriate indexes for all query patterns
  • ✅ Enable WiredTiger compression for storage efficiency
  • ✅ Set up replica set with proper read preferences
  • ✅ Implement sharding strategy for horizontal scaling
  • ✅ Configure connection pooling and timeouts
  • ✅ Enable profiling for slow query monitoring
  • ✅ Set up comprehensive backup and recovery procedures
  • ✅ Implement security with authentication and encryption
  • ✅ Configure monitoring and alerting
  • ✅ Optimize aggregation pipelines for performance

Conclusion

MongoDB has established itself as the leading document database, providing the flexibility, scalability, and performance needed for modern applications. With proper Ubuntu server deployment practices including replica sets, sharding, security, and monitoring, MongoDB can handle applications serving millions of users while maintaining high availability and data consistency.

The key to successful MongoDB deployment lies in understanding its distributed architecture and leveraging features like automatic failover, horizontal sharding, and rich query capabilities. By following the Ubuntu server setup procedures in this guide, you can achieve enterprise-grade MongoDB deployment with automated monitoring, security hardening, and performance optimization.

Whether you’re building content management systems, e-commerce platforms, or real-time analytics applications, MongoDB provides the foundation for rapid development and massive scale. Combined with proper indexing strategies, security implementation, and operational best practices, your MongoDB deployment can reliably serve your application’s data needs.

Ready to deploy MongoDB on your Ubuntu server? Use the installation scripts and configuration examples provided in this guide to build a production-ready MongoDB deployment that scales with your application requirements.