MongoDB write concerns let you control how many nodes in a replica set must acknowledge a write operation before it’s considered successful.

This is the same MongoDB replica set we’ve been using. We’ve got a primary mongo-primary:27017 and two secondaries mongo-secondary-1:27017 and mongo-secondary-2:27017.

Let’s insert a document into the testdb database, in the items collection, without specifying any write concern. This means it defaults to w:1, which is the primary acknowledging the write.

// Connect to mongo-primary:27017
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://mongo-primary:27017";

MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  var dbo = db.db("testdb");
  var myobj = { name: "Chair", price: 150 };
  dbo.collection("items").insertOne(myobj, function(err, res) {
    if (err) throw err;
    console.log("1 document inserted");
    db.close();
  });
});

After running this, you’ll see "1 document inserted". But critically, this write might not have even made it to the secondaries yet. If the primary crashes right now, that "Chair" document could be lost.

The default w:1 is fast, but it’s the least durable. It’s like telling a cashier "send me the receipt, I trust you got my money." The risk is on you.

To make it more durable, we can increase the write concern. Let’s try w:2. This means the primary and one secondary must acknowledge the write.

// Connect to mongo-primary:27017
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://mongo-primary:27017";

MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  var dbo = db.db("testdb");
  var myobj = { name: "Table", price: 300 };
  var writeConcern = { w: 2 }; // Primary and one secondary acknowledge
  dbo.collection("items").insertOne(myobj, writeConcern, function(err, res) {
    if (err) throw err;
    console.log("1 document inserted with w:2");
    db.close();
  });
});

This will take slightly longer than w:1 because the primary has to wait for replication. If the primary crashes now, the "Table" document is safe because at least one secondary has it.

The most durable write concern is w:majority. This means the write must be acknowledged by a majority of the voting nodes in the replica set. For our 3-node set, w:majority means at least 2 nodes must acknowledge. This is effectively the same as w:2 in our current setup, but it scales correctly as the replica set grows.

// Connect to mongo-primary:27017
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://mongo-primary:27017";

MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  var dbo = db.db("testdb");
  var myobj = { name: "Sofa", price: 700 };
  var writeConcern = { w: "majority" }; // Majority of voting nodes acknowledge
  dbo.collection("items").insertOne(myobj, writeConcern, function(err, res) {
    if (err) throw err;
    console.log("1 document inserted with w:majority");
    db.close();
  });
});

w:majority is the safest bet for critical data. It ensures that even if one node fails, your data is still available and durable on the remaining nodes.

There’s also j for journaling and wtimeout for timeouts. j:true means the write must be written to the journal on the primary before acknowledging. This offers even more durability, especially if the primary crashes before data is written to disk.

// Connect to mongo-primary:27017
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://mongo-primary:27017";

MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  var dbo = db.db("testdb");
  var myobj = { name: "Lamp", price: 50 };
  var writeConcern = { w: "majority", j: true, wtimeout: 5000 }; // Majority, journaled, 5s timeout
  dbo.collection("items").insertOne(myobj, writeConcern, function(err, res) {
    if (err) throw err;
    console.log("1 document inserted with w:majority, j:true, wtimeout:5000");
    db.close();
  });
});

The wtimeout setting is crucial. If the write doesn’t meet the w criteria within the specified time (e.g., 5000 milliseconds), the operation will fail with a timeout error, even if the write eventually succeeds on the nodes. This prevents your application from hanging indefinitely.

The trade-off is always performance. Higher write concerns mean more network round trips and waiting for replication, which increases latency. w:1 is the fastest. w:majority with j:true is the slowest.

Choosing the right write concern is about finding the sweet spot between how critical your data is and how much latency you can tolerate. For most applications, w:majority strikes a good balance.

What most people don’t realize is that the w value can also be a string representing a tag set. If you have a replica set with different hardware or network configurations, you can specify that a write must be acknowledged by nodes matching certain criteria, not just a raw count. For example, { w: { "dc": "eastus" } } would ensure the write is acknowledged by nodes tagged with dc: "eastus".

The next thing you’ll bump into is understanding read concerns and how they interact with write concerns to guarantee data consistency across your application.

Want structured learning?

Take the full Mongodb course →