DBAtlas · Database operations atlas

MongoDB replica set + sharding setup

Symptom

Goal: set up a replica set with automatic failover for MongoDB and extend it to a sharded cluster for horizontal scaling.

1. Start the mongod processes with the same replSet name

Start each replica set member with the same --replSet name and a reachable --bind_ip. In production, internal authentication with a keyFile or TLS is recommended. Aim for an odd number of voting members for a clear majority.

MongoDB

mongod --replSet rs0 --port 27017 --dbpath /data/n1 --bind_ip localhost,10.0.0.11
mongod --replSet rs0 --port 27017 --dbpath /data/n2 --bind_ip localhost,10.0.0.12
mongod --replSet rs0 --port 27017 --dbpath /data/n3 --bind_ip localhost,10.0.0.13

2. Initiate the replica set

Connect to one member with mongosh, call rs.initiate(), and define all members. This triggers the first election and a primary is chosen. Verify PRIMARY/SECONDARY roles with rs.status().

MongoDB

rs.initiate({
  _id: 'rs0',
  members: [
    { _id: 0, host: '10.0.0.11:27017' },
    { _id: 1, host: '10.0.0.12:27017' },
    { _id: 2, host: '10.0.0.13:27017' }
  ]
})
rs.status()

3. Add members, set priorities and an arbiter if needed

Add members later with rs.add(). priority determines which member tends to become primary (0 = never becomes primary). An arbiter only votes and holds no data; it is used as a tie-breaker with an even number of data nodes, but a real member is preferred for data safety. In arbiter-based topologies (especially PSA), majority write concern cannot be satisfied when a data node goes down and writes wait; on 5.0+ the cluster-wide default write concern may need to be set explicitly with setDefaultRWConcern before adding an arbiter.

MongoDB

rs.add({ host: '10.0.0.14:27017', priority: 0.5 })
// Arbiter only if really needed (a data-bearing member is preferred):
rs.addArb('10.0.0.15:27017')
// change priority:
cfg = rs.conf(); cfg.members[0].priority = 2; rs.reconfig(cfg)

4. Set up the config server replica set for sharding

The sharded cluster's metadata is kept in a config server replica set (--configsvr). It is itself initiated as a replica set; 3 members are recommended for high availability.

MongoDB

mongod --configsvr --replSet cfgrs --port 27019 --dbpath /data/cfg1 --bind_ip localhost,10.0.0.21
-- mongosh (on the config server):
rs.initiate({ _id: 'cfgrs', configsvr: true, members: [
  { _id: 0, host: '10.0.0.21:27019' },
  { _id: 1, host: '10.0.0.22:27019' },
  { _id: 2, host: '10.0.0.23:27019' } ] })

5. Start the shard replica sets and the mongos router

Each shard is its own replica set started with --shardsvr (data durability comes from intra-shard replication). The mongos router is started pointing at the config servers; applications connect to mongos.

MongoDB

mongod --shardsvr --replSet shard1rs --port 27018 --dbpath /data/s1 --bind_ip localhost,10.0.0.31
# initiate shard1rs with rs.initiate, then mongos:
mongos --configdb cfgrs/10.0.0.21:27019,10.0.0.22:27019,10.0.0.23:27019 --port 27017 --bind_ip localhost,10.0.0.40

6. Add the shards and shard the collection

Connect to mongos and add each shard replica set with sh.addShard(). Enable sharding on the database and distribute the collection by a shard key with sh.shardCollection(). Key choice is critical: it should have high cardinality and an even distribution. Monitor chunk distribution with sh.status().

MongoDB

sh.addShard('shard1rs/10.0.0.31:27018')
sh.addShard('shard2rs/10.0.0.32:27018')
sh.enableSharding('appdb')
sh.shardCollection('appdb.events', { customer_id: 'hashed' })
sh.status()
Open in DBAtlas →