DEV Community

Saurav Pandey
Saurav Pandey

Posted on

Demystifying MongoDB Write Concern and Read Concern in Node.js

What Are Write Concern and Read Concern?

In MongoDB, write concern and read concern are configuration settings that specify the level of guarantee you require when saving or retrieving data across a distributed cluster. A write concern determines how many database nodes must successfully record an update—and whether that data must be written to disk—before MongoDB reports success to your application. A read concern determines how fresh and consistent the data returned by a query must be, protecting your application from reading temporary data that might later be reversed.

Together, these two settings let developers choose where their application sits on the classic spectrum between maximum execution speed and rock-solid data safety.

The Real-World Analogy: Certified Mail vs. Kitchen Whiteboards

Imagine you run a bustling catering kitchen with multiple head chefs.

When taking an order, you have two choices for your write concern. You could scribble the customer's allergy request on a loose scrap of paper and immediately yell "Order placed!" (a fast write, but if you drop the paper, the order is lost). Alternatively, you could walk the order ticket over to the main order board, watch two sous-chefs sign off on it, and wait for them to file it in the metal lockbox before confirming the order with the customer. The second route takes several seconds longer, but you are guaranteed that the kitchen will never forget the order even if one chef walks out.

Now consider the read concern. If a waiter needs to know the soup of the day, they can either glance at a whiteboard where someone started drafting ideas with an erasable marker, or they can refuse to serve anything until they see the official menu stamped and approved by the head kitchen manager. Glancing at the draft whiteboard is instantaneous, but you might serve an experimental soup that the manager ultimately rejects five minutes later.

Why It Matters in Daily Software Engineering

Modern web architectures rarely run on a single database server. Instead, they use replica sets—groups of connected servers where one "primary" node handles writes and multiple "secondary" nodes replicate that data for redundancy.

If you leave MongoDB on default settings during high-traffic moments, subtle race conditions emerge:

  1. Rollback Catastrophes: If an API endpoint confirms an e-commerce order after writing only to the primary node, and that primary node suddenly experiences a hardware failure before syncing to secondary nodes, the cluster elects a new primary. Your customer's order is wiped out, yet your payment processor already charged their credit card.
  2. Dirty Reads: A background worker updates a bank balance. A microservice queries the secondary replica before the primary finishes replicating. If that transaction aborts or fails over, the microservice has operated on data that never officially existed.

By tuning write and read concerns, software engineers intentionally shield critical operations (payments, account transfers, credential updates) from data loss while letting low-risk operations (logging, view counters, user analytics) run with blazing speed.

Implementation in Node.js

Here is how you apply write and read concerns when working with the official MongoDB Node.js driver:

import { MongoClient } from 'mongodb';

const client = new MongoClient('mongodb://localhost:27017,localhost:27018/?replicaSet=rs0');

async function processPayment(orderId, paymentDetails) {
  await client.connect();
  const db = client.db('store');

  // Configure high-durability options for financial transactions
  const ordersCollection = db.collection('orders', {
    writeConcern: {
      w: 'majority',      // Must be acknowledged by more than half of the replica set nodes
      j: true,            // Must be written to the on-disk journal before confirming
      wtimeout: 5000      // Abort if replicas do not respond within 5 seconds
    },
    readConcern: {
      level: 'majority'   // Only read data committed by a majority of nodes
    }
  });

  // Step 1: Safely write with acknowledgment
  const writeResult = await ordersCollection.updateOne(
    { _id: orderId },
    { $set: { status: 'PAID', payment: paymentDetails } }
  );

  // Step 2: Read guaranteed, durable data
  const confirmedOrder = await ordersCollection.findOne({ _id: orderId });

  console.log('Payment processed safely:', confirmedOrder._id);
  return confirmedOrder;
}
Enter fullscreen mode Exit fullscreen mode

In this example, specifying w: 'majority' and j: true ensures that the write cannot be rolled back if the primary server abruptly crashes. Setting level: 'majority' on the read ensures your application reads only finalized records.

Key Takeaway

Database speed and data reliability exist on a continuous slider: write concern dictates how hard your cluster works to preserve your updates, while read concern dictates how strictly your cluster verifies the stability of what you fetch. Mastering both allows you to protect financial transactions and vital data without unnecessarily throttling high-volume, low-risk endpoints across your stack.


Buy Me A Coffee

Enjoyed this breakdown? Support my open-source work on Buy Me a Coffee or explore react-hook-lab!

Originally published on my blog. You can read the alternative breakdown here.

Top comments (0)