Back to Blog
MongoDB Transactions ACID

Understanding MongoDB Transactions

12 min read

Introduction

MongoDB introduced multi-document ACID transactions in version 4.0, bringing the reliability of traditional relational databases to the flexible world of NoSQL. In this article, I'll explain how transactions work in MongoDB and share practical patterns I've used in production systems.

Understanding when and how to use transactions is crucial for building robust applications that maintain data consistency.

What are ACID Transactions?

ACID stands for four key properties that guarantee reliable database transactions:

  • Atomicity: All operations in a transaction succeed or fail together
  • Consistency: Database moves from one valid state to another
  • Isolation: Concurrent transactions don't interfere with each other
  • Durability: Committed transactions persist even after system failures

Basic Transaction Pattern

Here's a basic pattern for implementing transactions in MongoDB with Node.js:

const session = client.startSession();

try {
  session.startTransaction();
  
  // Perform multiple operations
  await ordersCollection.insertOne(order, { session });
  await inventoryCollection.updateOne(
    { productId: order.productId },
    { $inc: { quantity: -order.quantity } },
    { session }
  );
  
  await session.commitTransaction();
} catch (error) {
  await session.abortTransaction();
  throw error;
} finally {
  session.endSession();
}

Using withTransaction() Helper

MongoDB provides a convenient withTransaction() helper that handles retries automatically:

const session = client.startSession();

try {
  await session.withTransaction(async () => {
    await ordersCollection.insertOne(order, { session });
    await inventoryCollection.updateOne(
      { productId: order.productId },
      { $inc: { quantity: -order.quantity } },
      { session }
    );
  });
} finally {
  await session.endSession();
}

This approach automatically retries on transient errors and handles commit/abort logic for you.

Best Practices

  • Keep transactions short: Long-running transactions hold locks and can cause performance issues
  • Limit operations: Try to keep under 1000 document modifications per transaction
  • Use replica sets: Transactions require a replica set (or sharded cluster in 4.2+)
  • Handle errors properly: Always implement retry logic for transient errors
  • Consider alternatives: Sometimes denormalization or embedded documents are better than transactions

Common Pitfalls

1. Forgetting the Session Parameter

Every operation in the transaction must include the session. Missing it means the operation runs outside the transaction:

// Wrong - runs outside transaction
await collection.insertOne(doc);

// Correct - part of transaction
await collection.insertOne(doc, { session });

2. Transaction Timeout

Transactions have a default 60-second timeout. For longer operations, consider breaking them into smaller batches or increasing the timeout.

Conclusion

MongoDB transactions provide powerful guarantees for data consistency, but they should be used judiciously. In many cases, MongoDB's document model allows you to avoid transactions entirely by embedding related data in a single document.

When you do need transactions, follow the best practices outlined above to ensure optimal performance and reliability. The withTransaction() helper is your friend for handling the complexity of retries and error handling.

Found this helpful? Share it!