Introduction Building an index on a large MongoDB collection can block writes for extended periods, especially on MongoDB 4.2 and earlier where foreground builds acquire exclusive locks. Even background builds in newer versions can cause write stalls when the collection has millions of documents.
Symptoms - Write operations timeout with `LockBusy` during index creation - `db.currentOp()` shows long-running `createIndex` operation blocking other ops - Application experiences write latency spikes correlating with index build start time - Index build fails with `Index build aborted due to stepdown` during replica set failover - Disk I/O spikes during index build causing slowdown on all operations
Common Causes - Foreground index build on MongoDB 4.2 or earlier blocking all database writes - Building index on a collection with millions of documents without `background: true` - Insufficient memory for the index build sort phase, causing disk spills - Replica set stepdown interrupting index builds - Building multiple indexes simultaneously competing for I/O
Step-by-Step Fix 1. **Check current index build operations**: ```javascript db.currentOp({ "op": "command", "msg": /^Index Build/ }) // Or for all ops blocking writes db.currentOp({ "waitingForLock": true }) ```
- 1.Kill a stuck or problematic index build:
- 2.```javascript
- 3.var ops = db.currentOp({ "msg": /^Index Build/ });
- 4.ops.inprog.forEach(function(op) {
- 5.print("Killing op: " + op.opid);
- 6.db.killOp(op.opid);
- 7.});
- 8.
` - 9.Build the index in the background (MongoDB 4.2+)":
- 10.```javascript
- 11.// Background build is default in MongoDB 4.2+
- 12.db.collection.createIndex({ status: 1, created_at: -1 })
// For explicit control in older versions: db.collection.createIndex({ status: 1 }, { background: true }) ```
- 1.Build indexes on secondaries first (rolling index build)":
- 2.```javascript
- 3.// Step 1: Stop the balancer (for sharded clusters)
- 4.sh.stopBalancer();
// Step 2: Build on each secondary one at a time // Connect to a secondary and build db.collection.createIndex({ field: 1 });
// Step 3: Step down the primary rs.stepDown();
// Step 4: Build on the new primary (was a secondary with the index) // The index build on the new primary will be fast as it already exists ```
- 1.Use the inMemory build option for faster creation (MongoDB 5.0+)":
- 2.```javascript
- 3.// Requires sufficient RAM to hold the index in memory
- 4.db.collection.createIndex(
- 5.{ user_id: 1, created_at: -1 },
- 6.{ buildIndexes: true }
- 7.);
- 8.
` - 9.**Monitor index build progress":
- 10.```javascript
- 11.// Check index build progress
- 12.db.adminCommand({ createIndexes: "collection", indexes: [] });
// Check indexes built so far db.collection.getIndexes();
// Monitor disk I/O during build // mongostat --discover 1 ```