Skip to main content
unbound mongodb at scale

Write Concerns: Durability vs Throughput

3 min read Chapter 58 of 72

Write Concerns

Write concern controls how many replica set members must acknowledge a write before the driver considers it successful. A weaker write concern returns faster but risks data loss. A stronger write concern returns slower but guarantees durability.

Write concern diagram. Shows w:1 (primary acknowledges, returns immediately, secondary replicates asynchronously). Shows w:majority (primary writes, waits for 1 secondary to replicate and acknowledge, then returns). Shows j:true (waits for journal flush before acknowledging). Timeline comparison for w:0, w:1, w:majority with latency markers.

Write Concern Levels

LevelAcknowledgmentDurability on primary crashLatency
w: 0 (unacknowledged)None. Fire and forget.Data may be lost~0ms
w: 1 (default)Primary acknowledgesData may be lost (not yet replicated)~2ms
w: 1, j: truePrimary journal flushDurable on primary disk~5ms
w: "majority"Majority of voting membersDurable (survives primary failure)~8ms
w: "majority", j: trueMajority + journal flushMaximum durability~12ms
// Configure write concern at the client level
MongoClientSettings settings = MongoClientSettings.builder()
    .applyConnectionString(new ConnectionString(uri))
    .writeConcern(WriteConcern.MAJORITY.withJournal(true))
    .build();

// Override per-collection
MongoCollection<Document> readings = database.getCollection("readings")
    .withWriteConcern(WriteConcern.W1);

// Override per-operation
collection.withWriteConcern(WriteConcern.MAJORITY)
    .insertOne(criticalDocument);

What Happens When the Primary Crashes

With w: 1, the primary acknowledges the write after storing it in memory (and eventually flushing to the journal). If the primary crashes before replicating to a secondary:

  1. A secondary is elected as the new primary.
  2. The new primary does not have the unreplicated write.
  3. When the old primary comes back online, it has a write that the new primary does not. This write is rolled back (written to a rollback file for manual recovery).
  4. The application received a success acknowledgment for a write that no longer exists.

With w: "majority", the primary waits until a majority of members (including itself) have the write. If the primary crashes after the majority acknowledgment, the write exists on at least one other member. The new primary will have the write.

The Cost of Durability

@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public class WriteConcernBenchmark {

    @Benchmark
    public void w0() {
        collection.withWriteConcern(WriteConcern.UNACKNOWLEDGED)
            .insertOne(reading);
    }

    @Benchmark
    public void w1() {
        collection.withWriteConcern(WriteConcern.W1)
            .insertOne(reading);
    }

    @Benchmark
    public void wMajority() {
        collection.withWriteConcern(WriteConcern.MAJORITY)
            .insertOne(reading);
    }

    @Benchmark
    public void wMajorityJournal() {
        collection.withWriteConcern(WriteConcern.MAJORITY.withJournal(true))
            .insertOne(reading);
    }
}

// Results (3-member replica set, same data center):
// w:0          -> 48,000 ops/sec
// w:1          -> 22,000 ops/sec
// w:majority   -> 14,000 ops/sec
// w:majority,j -> 11,000 ops/sec

Each step up in durability costs approximately 30-50% throughput. The cost comes from waiting for replication (network round trip to secondaries) and journal flushes (disk I/O).