MongoDB path · Writes you can trust · Topic 8 of 12

Write concern, read concern, read preference

Not started

When a driver reports acknowledged: true, it means the server confirmed the write to the level you asked for, nothing more. That level is the write concern. Two more settings decide what a later read can see: the read concern (how committed the data must be) and the read preference (which member answers). Together they are your consistency and durability settings, and each trades latency or availability for safety.

Why it matters: acknowledged: true sounds final. Whether that write survives a failover, and whether the next read sees it, depends on three settings most code leaves at their defaults without knowing what they are.

  1. 1Write concern says who must confirm

    w: 1 waits for the primary; w: "majority" waits until a majority of data-bearing voters have the write in their oplog. Majority is the default since 5.0 for most replica sets.

  2. 2A write concern error is not a rollback

    If wtimeout expires, the client gets an error but the write stays on the primary and may still replicate, or later roll back.

  3. 3Read concern says what may be returned

    local returns the member's latest data, which could still roll back; majority returns only majority-committed data; linearizable and snapshot are stronger still.

  4. 4Read preference says which member answers

    primary by default. secondary and nearest spread reads but can return stale data, because replication is asynchronous.

1

How it works

The explanation, with examples you can run.

What the defaults are

db.adminCommand({ getDefaultRWConcern: 1 })
{ "defaultReadConcern": { "level": "local" },  "defaultWriteConcern": { "w": "majority", "wtimeout": 0 },  "defaultWriteConcernSource": "implicit", "defaultReadConcernSource": "implicit" }

Since MongoDB 5.0 the implicit default write concern is w: "majority", with one exception: in a replica set with arbiters where the data-bearing members are not more than a majority of voters (the classic primary-secondary-arbiter), it is w: 1. Many older drivers and code samples also set w: 1 explicitly.

Write concern

SettingAcknowledged whenCan it roll back?
w: 0Never; fire and forgetYes, and you will not know if it failed
w: 1The primary has applied itYes, if the primary fails before a secondary copies it
w: "majority"A majority of data-bearing voting members have it in their oplog (journaled by default)No
j: trueAlso written to the on-disk journalj: true alone does not prevent rollback

wtimeout limits how long to wait for the acknowledgement. It does not cancel anything. With one of three members stopped:

db.payments.insertOne({ _id: 2, amount: 700 }, { writeConcern: { w: 3, wtimeout: 2000 } })
MongoWriteConcernError: waiting for replication timed out{ code: 64, codeName: 'WriteConcernTimeout', errInfo: { wtimeout: true, ... } }
db.payments.countDocuments({ _id: 2 })   // 1

The insert failed from the client's point of view but the document exists. After a write concern error or a network error the outcome is unknown, which is why retries should be idempotent (an upsert keyed on a business id, not a blind insert).

Read concern

  • local (default): the member's latest data, which may include writes that are later rolled back.
  • available: like local; on sharded clusters it can also return orphaned documents. Fastest, weakest.
  • majority: only data acknowledged by a majority, so it never rolls back. It may be slightly behind the newest writes.
  • linearizable: majority data that reflects every majority write completed before the read began; primary only, slower.
  • snapshot: a consistent point-in-time view, used by transactions.

Read preference

primary (default), primaryPreferred, secondary, secondaryPreferred and nearest. Reading from secondaries spreads load and keeps reads working during an election, but replication is asynchronous, so a secondary can be seconds behind under load. maxStalenessSeconds excludes secondaries that are too far behind. For read-your-writes across members, use a causally consistent session with majority read and write concern; otherwise read from the primary.

2

Check yourself

3 questions. Get them all right to finish this topic.

  1. 1.A write with { w: 3, wtimeout: 2000 } returns a WriteConcernTimeout error because one secondary is down. Is the document in the database?
  2. 2.Users update their profile and the next page, read with readPreference secondary, shows the old value. Why?
  3. 3.Which read concern can return data that is later rolled back?

0 of 3 right so far. Get all three to finish this topic.