Skip to content

Read & Write Concern

Write concern and read concern let you control how safely data is written and how fresh the data you read is.

Think of a restaurant kitchen:

  • Write Concern (how safely is the order recorded?):

    • w: 1 — The chef acknowledges they saw the order
    • w: "majority" — The chef AND two sous-chefs all confirm
    • j: true — The order is written in the permanent log book
  • Read Concern (how fresh is the data you read?):

    • local — Whatever the waiter has in memory right now
    • majority — Only serve dishes that multiple chefs have confirmed

Write concern controls when a write operation is acknowledged as successful.

flowchart LR
Client[Application] -->|Write request| Primary[Primary Node]
Primary -->|w: 1 - Acknowledged| Respond1[✅ Client notified<br/>when primary confirms]
Primary --> Secondary[Secondary 1]
Primary --> Secondary2[Secondary 2]
Primary -->|w: majority - Acknowledged| Respond2[✅ Client notified<br/>when majority confirm]
style Respond1 fill:#f59e0b,color:#fff
style Respond2 fill:#7c3aed,color:#fff
// Write concern options (in mongosh):
db.users.insertOne(
{ name: "Alice" },
{ writeConcern: { w: 1 } } // default — primary confirms
)
db.users.insertOne(
{ name: "Alice" },
{ writeConcern: { w: "majority" } } // majority of replica set confirms
)
db.users.insertOne(
{ name: "Alice" },
{ writeConcern: { w: "majority", j: true } } // + journal (written to disk)
)
// In Mongoose:
await User.create({ name: "Alice" }) // default w: 1
await User.create({ name: "Alice" }, { w: "majority", j: true })
Write ConcernDurabilitySpeed
w: 1 (default)Primary confirms⚡ Fastest
w: "majority"Most nodes confirm🐢 Slower
w: "majority" + j: trueWritten to journal on most nodes🐌 Slowest but safest
w: 0Fire and forget — no acknowledgement⚡ Fastest (risk of data loss)

Read concern controls which data is visible to a read operation.

// Read concern options:
db.users.find().readConcern("local") // default — whatever the node has
db.users.find().readConcern("majority") // only data confirmed by majority
db.users.find().readConcern("linearizable") // most recent, strongest guarantee
db.users.find().readConcern("available") // fastest, no consistency guarantee
Read ConcernConsistencySpeedUse When
local (default)None⚡ FastestNon-critical reads
majorityHigh🐢Financial data, critical reads
linearizableAbsolute strongest🐌Absolute latest value needed
availableNone⚡ FastSharded collections, doesn’t matter if stale

Read preference controls which replica set member handles the read.

// In connection string:
mongoose.connect(uri, {
readPreference: 'secondaryPreferred'
});
// Options:
// - primary: Always primary (default)
// - primaryPreferred: Primary first, fallback to secondary
// - secondary: Always secondary
// - secondaryPreferred: Secondary first, fallback to primary
// - nearest: Lowest latency node
flowchart TB
Q1{Is this critical<br/>financial data?}
Q1 -->|Yes| WC1[Write: w: majority, j: true<br/>Read: majority]
Q1 -->|No| Q2{Is this a<br/>real-time feature?}
Q2 -->|Yes| WC2[Write: w: 1<br/>Read: local]
Q2 -->|No| Q3{Is read throughput<br/>very high?}
Q3 -->|Yes| WC3[Write: w: 1<br/>Read: secondaryPreferred]
Q3 -->|No| WC4[Default settings<br/>w: 1, readConcern: local]
style WC1 fill:#7c3aed,color:#fff
style WC2 fill:#3b82f6,color:#fff
style WC3 fill:#059669,color:#fff
style WC4 fill:#f59e0b,color:#fff

  • Write concern controls how many nodes confirm a write before the app is told “done”
  • Read concern controls how fresh/consistent the data you read is
  • Read preference controls which node handles your read (primary vs secondary)
  • Default settings (w: 1, local) are fine for most apps
  • Use stronger settings for financial/critical data; use weaker settings for speed

Next: Change Streams →