Write concern, read concern and read preference
Tune durability, consistency and routing per operation: w and j, local/majority/snapshot/linearizable reads, primary/secondary routing and causal consistency.
- Choose write concern: w: 1, w: "majority", j: true, wtimeout
- Choose read concern: local, available, majority, snapshot, linearizable
- Route reads with read preference and maxStalenessSeconds
- Explain rollback risk and causal consistency
conceptThe concept
Open the interactive lesson to use this diagram.
Write concern is how many members must acknowledge a write before the client is told it succeeded. w: 1: primary only. w: "majority" (default since 5.0): a majority of voting members, which means the write survives any failover. j: true: written to the on-disk journal. wtimeout: stop waiting (the write is not undone).
Read concern is which data a read may return:
local(default): the latest data on that node, which might later be rolled back.available: like local; on sharded clusters may return orphans. Fastest.majority: only data acknowledged by a majority; never rolled back.snapshot: a consistent point-in-time view (transactions, and reads withatClusterTime).linearizable: reflects all majority writes completed before the read started; primary only, slow.
Read preference is where reads go: primary (default), primaryPreferred, secondary, secondaryPreferred, nearest, optionally with tag sets and maxStalenessSeconds (90 or more).
whyWhy it matters
These settings are the dial between latency and safety. With w: 1, a write acknowledged by a primary that crashes before replicating it is rolled back after failover, and the client thinks it succeeded. With secondary reads, a user may not see the profile change they just saved. Knowing these trade-offs is essential for architects and a common interview topic.
Use caseReal-world scenario
Payments use w: "majority" and read their own writes from the primary. The analytics dashboard reads from a secondary tagged { workload: "analytics" } with secondaryPreferred, accepting a few seconds of lag. A "user just updated settings" flow uses causally consistent sessions so a subsequent secondary read waits until it has caught up to that write.
Try itExamples
Run and edit these in the interactive lesson.
db.orders.insertOne({ orderNo: "ORD-WC-1", status: "paid", createdAt: new Date(), total: 10 }, { writeConcern: { w: "majority", j: true, wtimeout: 5000 } })
db.orders.updateOne({ orderNo: "ORD-WC-1" }, { $set: { status: "shipped" } }, { writeConcern: { w: 1 } })db.orders.find({ status: "shipped" }).readPref("secondaryPreferred").readConcern("majority").limit(2)
db.adminCommand({ getDefaultRWConcern: 1 })mongodb://db1,db2,db3/shop?replicaSet=rs0&w=majority&readPreference=secondaryPreferred&maxStalenessSeconds=120&readPreferenceTags=dc:eastinternalsUnder the hood
The primary tracks each secondary's replicated optime. A majority write waits until the majority commit point passes its optime. Majority reads serve data from the majority-committed snapshot, which WiredTiger keeps available; if secondaries lag, that snapshot stays old and pins history in the cache (cache pressure on the primary). Causal consistency works by carrying operationTime/clusterTime from one operation into the next (afterClusterTime), so a secondary waits until it has applied up to that point.
Try it in the Replica set simulator: write with w:1, kill the primary before replication, and watch the write get rolled back.
Avoid / preferDo this, not that
db.payments.insertOne(p, { writeConcern: { w: 1 } })db.payments.insertOne(p, { writeConcern: { w: "majority", j: true, wtimeout: 5000 } })A w:1 write acknowledged by a primary that then fails over can be rolled back. Majority acknowledgement survives any single failure.
db.orders.insertOne(o)
db.orders.find({ _id: o._id }).readPref("secondary") // may return nothingconst s = db.getMongo().startSession({ causalConsistency: true })
// writes with w:"majority", reads with readConcern "majority" in that sessionA secondary may not have replicated your write yet. A causally consistent session guarantees you read your own writes even from secondaries.
PitfallsCommon mistakes
- Using
w: 0orw: 1for business-critical data. - Reading from secondaries to "scale reads" without accepting staleness; it also moves load rather than removing it.
- Treating
wtimeoutas a rollback; the write may still complete later. - Arbiters in PSA topologies: with one data-bearing member down, majority writes cannot be acknowledged and the majority commit point stalls, increasing cache pressure.
LimitsWhen not to use it
In a PSA set with the secondary down, w: "majority" writes stall because the arbiter cannot acknowledge writes. readConcern: "linearizable" is slow and only meaningful for single-document reads on the primary. Secondary reads do not scale reads that need fresh data.
SecuritySecurity notes
Security events need durability too. A revoked token, a lockout counter or an audit record written with w:1 can vanish in a rollback, quietly undoing the revocation. Write them with w: "majority".
ChallengeTry it yourself
Insert a "token-revoked" event into a scratch collection with majority write concern, journaling and a 5-second timeout, then read it back with read concern majority.
Show one solution
db.audit_lab.drop()
db.audit_lab.insertOne({ event: "token-revoked", at: new Date() }, { writeConcern: { w: "majority", j: true, wtimeout: 5000 } })
db.audit_lab.find({}, { _id: 0, event: 1 }).readConcern("majority")InterviewQuestions you should be able to answer
What happens to a w:1 write if the primary crashes right after acknowledging it?
If the write had not reached a secondary that becomes primary, the new primary does not have it. When the old primary rejoins it rolls back the write (saved to a rollback directory). The client got success, but the data is gone from the replica set. w: "majority" prevents this because a majority-acknowledged write is guaranteed to be on whichever member wins the election.
Explain read concern majority vs linearizable.
majority returns data acknowledged by a majority as of the node's majority-committed snapshot; it may not include the very latest majority writes (it can be slightly stale) but is never rolled back. linearizable additionally guarantees the read reflects all writes acknowledged before the read began, by confirming the node is still primary with a majority write; it works only on the primary for single-document reads and is slower.
How do you get read-your-own-writes on secondaries?
Use a causally consistent session with w: "majority" writes and readConcern: "majority" reads. The driver passes the operation time of the write as afterClusterTime to the secondary read, which waits until the secondary has replicated that far.
QuizCheck your understanding
4 questions with instant feedback in the interactive lesson; a wrong answer goes into your review deck.