Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

MongoDB Transactions

ACID Transactions in MongoDB

Since MongoDB 4.0, multi-document ACID transactions are supported on replica sets, and since 4.2 on sharded clusters. Transactions guarantee Atomicity (all or nothing), Consistency (data remains valid), Isolation (concurrent transactions don't interfere), and Durability (committed data persists).

For single-document operations, MongoDB has always been atomic. Multi-document transactions are needed when you need to update multiple documents or collections atomically.

Using Transactions with Sessions

startTransaction, commitTransaction, abortTransaction
// Example: Transfer funds between two accounts atomically
const session = db.getMongo().startSession()

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

try {
  const accounts = session.getDatabase("bank").accounts

  // Debit from sender
  accounts.updateOne(
    { accountId: "ACC001", balance: { $gte: 500 } },
    { $inc: { balance: -500 } },
    { session }
  )

  // Credit to receiver
  accounts.updateOne(
    { accountId: "ACC002" },
    { $inc: { balance: 500 } },
    { session }
  )

  // Commit both operations atomically
  session.commitTransaction()
  print("Transaction committed successfully")

} catch (error) {
  // Rollback all changes if anything fails
  session.abortTransaction()
  print("Transaction aborted: " + error.message)

} finally {
  session.endSession()
}

withTransaction() Helper

withTransaction() — Automatic Retry and Cleanup
// withTransaction() handles retries and session cleanup automatically
const session = db.getMongo().startSession()

session.withTransaction(async () => {
  const orders = session.getDatabase("myapp").orders
  const inventory = session.getDatabase("myapp").inventory

  // Create the order
  await orders.insertOne({
    userId: ObjectId("u1"),
    productId: ObjectId("prod1"),
    qty: 2,
    total: 259.98,
    status: "confirmed",
    createdAt: new Date()
  }, { session })

  // Decrement inventory
  await inventory.updateOne(
    { productId: ObjectId("prod1"), stock: { $gte: 2 } },
    { $inc: { stock: -2 } },
    { session }
  )
})

session.endSession()

Transaction Options and Best Practices

Transaction Options and Limitations
// Transaction options
session.startTransaction({
  readConcern:  { level: "snapshot" },  // snapshot, majority, local
  writeConcern: { w: "majority", j: true, wtimeout: 5000 },
  maxCommitTimeMS: 10000   // max time to wait for commit
})

// Read concern levels:
// "local"    — reads most recent data (may not be committed)
// "majority" — reads data confirmed by majority of replica set
// "snapshot" — reads consistent snapshot at transaction start (recommended)

// Write concern:
// w: 1         — acknowledged by primary only
// w: "majority" — acknowledged by majority of replica set (recommended)
// j: true      — write to journal before acknowledging

// Key limitations:
// - Transactions have a 60-second default timeout
// - Maximum 1000 documents modified per transaction (configurable)
// - Cannot create or drop collections inside a transaction
// - Avoid long-running transactions — they hold locks
// - Prefer single-document operations when possible (always atomic)
// - Requires a replica set (even a single-node replica set works)

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.