Lesson 0008 · Durability
Two orthogonal dials on every write: w controls how many nodes must acknowledge, j controls whether the journal flushed to disk. They don't imply each other — and combining them precisely is how you tune the durability/latency trade-off.
The oplog is idempotent. Why does that property matter for crash recovery?
A 3-node replica set: to win a primary election, a candidate secondary must satisfy:
A MongoDB client's default read preference routes reads to:
The default write concern (w: 1) means the primary acknowledged your write as soon as it hit its own oplog.
But if the primary crashes right after, and the secondaries haven't replicated that oplog entry yet, the next elected primary won't have it — the write is silently rolled back.
This isn't a bug; it's a trade-off. Write concern and read concern let you choose exactly where on the durability/latency spectrum you sit.
j: true and w separately because they're easy to conflate. Here's the definitive split:j: true — one node's journal question: "Did this node flush the write to its WAL before acking?" About surviving a process crash on one machine.w: N — the replication question: "How many nodes acknowledged this write?" About surviving a node failure.w dialw specifies how many replica set members must acknowledge the write before the driver returns to the application.
— MongoDB Manual: "Write concern describes the level of acknowledgment requested from MongoDB for write operations to a standalone mongod or to replica sets or to sharded clusters."
| Value | Meaning | Risk |
|---|---|---|
w: 0 | Fire and forget — no acknowledgment at all | No error reporting; data loss on any failure |
w: 1 (default) | Primary has written to its oplog | Rollback if primary crashes before replication |
w: 2, w: N | Primary + N−1 secondaries acknowledged | Lower rollback risk; higher latency |
w: "majority" | A majority of voting members acknowledged | Minimal — any elected primary already has the write |
w: "majority" is the key value: because elections require a majority, any secondary that wins an election is guaranteed to already have the write. Rollback of a majority-acknowledged write is essentially impossible under normal failure modes.
— MongoDB Manual: "If you use writeConcern: majority, MongoDB returns acknowledgment of the write operation after a majority of the voting members have applied the write operation."
j dialj is a per-write flag that tells the primary whether to wait for the journal (write-ahead log) to flush to disk before sending acknowledgment.
— MongoDB Manual: "The j option requests acknowledgment that the write operation has been written to the on-disk journal."
| Value | Meaning | Risk |
|---|---|---|
j: false (default) | Primary acks without waiting for journal flush; write is in memory (committed to oplog buffer) | If the primary process crashes before the next journal write (~100 ms), the write is lost even on that node |
j: true | Primary flushes the write to the WAL journal before acking | Adds latency (~journal flush time, sub-millisecond on SSD); write survives any single-process crash |
This is the direct analog of the WiredTiger journal from lesson 0002: the journal flushes every 100 ms by default.
Setting j: true forces an immediate flush — the same way PostgreSQL's synchronous_commit = local forces a local WAL sync.
w and j| Combination | Survives | Doesn't survive | Use when |
|---|---|---|---|
w: 1, j: false (default) |
Network errors (you got an ack) | Primary process crash before journal flush; primary node failure before replication | Bulk imports, caches, metrics — data you can reconstruct |
w: 1, j: true |
Primary process crash | Primary node failure before replication — write may still roll back | Durable on primary, not guaranteed replicated; middle ground |
w: "majority", j: false |
Primary node failure (majority have it) | Simultaneous crash of majority members before journal flush — unlikely but possible | Read-heavy systems where replicated > journaled |
w: "majority", j: true |
Primary crash + primary node failure; rollback impossible under normal failure | Correlated failure of a majority of nodes simultaneously | Financial systems, order processing, anything where the write must survive |
Write concern controls what's durable when you write. Read concern controls what you see when you read — specifically whether you might read data that could later be rolled back. — MongoDB Manual: "The readConcern option allows you to control the consistency and isolation properties of the data read from replica sets and replica set shards."
| Level | Reads | Can be rolled back? |
|---|---|---|
local (default) | Most recent data on the node, regardless of replication state | Yes — if the node was primary and loses an election, unacknowledged writes roll back |
majority | Data acknowledged by a majority of voting members | No — only data that can't be rolled back |
linearizable | Reflects all majority-acknowledged writes before the read started; reads always from primary with extra verification | No — strongest guarantee, highest latency |
The practical pair: if your write uses w: "majority", your read using readConcern: "majority" sees only data that has met that same bar. Together they give you the MongoDB equivalent of serializable isolation on a distributed system — without a transaction.
| MongoDB setting | Postgres analog | What it means |
|---|---|---|
w: 1, j: false | synchronous_commit = off | Fast ack; data in memory; may lose recent commits on crash |
w: 1, j: true | synchronous_commit = local | Local WAL flush before ack; durable on one node |
w: "majority", j: true | synchronous_commit = on (or remote_apply) | Wait for remote WAL confirmation; durable on majority; rollback impossible |
readConcern: "majority" | Reading from primary with synchronous_commit = on | Only see data that can't be lost to a failover |
The structural difference: Postgres applies synchronous_commit globally for the server (or per-session); MongoDB sets w and j per write operation or per collection default. Per-operation granularity is more flexible but also more dangerous — it's easy to use the wrong concern on a critical write.
The default write concern w: 1 risks data loss because:
j: true on a write means the driver waits for:
w: "majority", j: false means the write:
readConcern: "majority" guarantees you won't read data that:
The closest Postgres analog to w: "majority", j: true is:
db.col.insertOne({x: 1}, { writeConcern: { w: "majority", j: true } }) and observe the extra latency vs the default. Then try db.col.find().readConcern("majority") to see majority-read in action. In a 3-node set you can kill the primary immediately after a w: 1 write and watch the new primary roll it back.