Transactions, sessions and read/write concerns

Use sessions for causal consistency, wrap multi-document changes in a transaction correctly, and choose read and write concerns that match what the business can tolerate losing.

Sessions and causal consistency

A session is the context for a sequence of operations. It carries an operation time and a cluster time, which is what lets the driver guarantee that a read following a write on the same session sees that write even when it is served by a different member.

const session = db.getMongo().startSession();
const s = session.getDatabase("shop");

s.orders.insertOne({ customer: "Ada", status: "new" });
s.orders.findOne({ customer: "Ada" });      // sees the insert above

session.endSession();

// causal consistency is on by default; this makes it explicit
const causal = db.getMongo().startSession({ causalConsistency: true });
  • Causal consistency is about ordering within one session, not about global freshness. Two sessions can still observe events in different orders.
  • Sessions are also the mechanism behind retryable writes: the server tracks the transaction number so a retried write is not applied twice.
  • Always end a session. An abandoned session pins its server-side state until the timeout expires.

Multi-document transactions

const session = db.getMongo().startSession();
const shop = session.getDatabase("shop");

session.startTransaction({
  readConcern: { level: "snapshot" },
  writeConcern: { w: "majority" },
  readPreference: "primary"
});

try {
  shop.orders.updateOne({ _id: orderId }, { $set: { status: "paid" } });
  shop.inventory.updateOne({ sku: "LAMP-01" }, { $inc: { onHand: -1 } });
  session.commitTransaction();
} catch (err) {
  session.abortTransaction();
  throw err;
} finally {
  session.endSession();
}
  • Transactions require a replica set or a sharded cluster. A standalone server does not support them, which is one more reason to develop against the same topology you deploy.
  • A transaction is limited to 60 seconds by transactionLifetimeLimitSeconds and to 16 MB of oplog. Never wait on an external API or a user response inside one.
  • All operations in the transaction must use the same session. An operation that omits it runs outside the transaction and is not rolled back.
  • Reads inside a transaction use snapshot read concern, and writes take document-level locks that other transactions must wait for.

Read and write concerns

SettingMeaning
w: 1Acknowledged by the primary's memory only
w: "majority"Replicated to a majority; survives an election
w: 0Fire and forget; no acknowledgement, no error on failure
j: trueAcknowledged after the journal write, so a crash does not lose it
readConcern: localWhatever the node has, including writes that a failover could roll back
readConcern: majorityOnly data that a majority has acknowledged and cannot be rolled back
readConcern: snapshotA consistent point-in-time view; required inside transactions
readPreferenceWhich member is eligible to serve a read

The two settings are independent and both matter. Writing with w: "majority" and then reading with readConcern: local from a secondary can still return an older value, because the read is served by a member that may not have applied the write yet.

⚠️
w: 0 is much faster and much more dangerous: the driver reports success without knowing whether any node received the write, so a failure is invisible and a failover can erase it. Reserve it for telemetry you can genuinely afford to lose.

FAQ

Do I need transactions?
Only when one logical change must touch more than one document atomically. A single-document update is already atomic, and modelling the change so that it fits in one document is both simpler and faster than reaching for a transaction.
Why did my transaction fail after a minute?
That is transactionLifetimeLimitSeconds. The server aborts a transaction that runs or idles too long, because it pins a snapshot and holds locks the whole time. Keep transactions short and never perform external calls inside one.

Documents, collections and queries Drivers and ODMs in application code

Last refreshed 2026-09-18.