Production Considerations

Feature Compatibility

The featureCompatibilityVersion of all members of the replica set must be 4.0 or greater.

Runtime Limit

By default, a transaction must have a runtime of less than one minute. You can modify this limit using transactionLifetimeLimitSeconds. Transactions that exceeds this limit are considered expired and will be aborted by a periodic cleanup process.

Oplog Size Limit

When the transaction commits, a single oplog (operations log) entry is created if the transaction contains any write operations. That is, the individual operations in the transactions do not have a corresponding oplog entry. Instead, a single oplog entry contains all of the write operations within a transaction. The oplog entry for the transaction must be within the BSON document size limit of 16MB.

WiredTiger Cache

To prevent storage cache pressure from negatively impacting the performance:

  • When you abandon a transaction, abort the transaction.
  • When you encounter an error during individual operation in the transaction, abort the transaction and retry the transaction.

The transactionLifetimeLimitSeconds also ensures that expired transactions are aborted periodically to relieve storage cache pressure.

Transactions and Locks

By default, transactions waits up to 5 milliseconds to acquire locks required by the operations in the transaction. If the transaction cannot acquire its required locks within the 5 milliseconds, the transaction aborts.

Transactions release all locks upon abort or commit.


When creating or dropping a collection immediately before starting a transaction, if the collection is accessed within the transaction, issue the create or drop operation with write concern "majority" to ensure that the transaction can acquire the required locks.

Lock Request Timeout

You can use the maxTransactionLockRequestTimeoutMillis parameter to adjust how long transactions wait to acquire locks. Increasing maxTransactionLockRequestTimeoutMillis allows operations in the transactions to wait the specified time to acquire the required locks. This can help obviate transaction aborts on momentary concurrent lock acquisitions, like fast-running metadata operations. However, this could possibly delay the abort of deadlocked transaction operations.

You can also use operation-specific timeout by setting maxTransactionLockRequestTimeoutMillis to -1.

Pending DDL Operations and Transactions

If a multi-document transaction is in progress, new DDL operations that affect the same database(s) wait behind the transaction. While these pending DDL operations exist, new transactions that access the same database as the pending DDL operations cannot obtain the required locks and will abort after waiting maxTransactionLockRequestTimeoutMillis. In addition, new non-transaction operations that access the same database will block until they reach their maxTimeMS limit.

To illustrate, compare the following two situations:

Consider a situation where an in-progress transaction performs various CRUD operations on the employees collection in the hr database. While that transaction is in progress, a separate transaction that accesses the foobar collection in the hr database can start and complete.

However, consider a situation where an in-progress transaction performs various CRUD operations on the employees collection in the hr database and a separate DDL operation is issued to create an index on the fluffy collection in the hr database. The DDL operation waits for the transaction to finish.

While the DDL operation is pending, a new transaction attempts to access the foobar collection in the hr database. If the DDL operation remains pending for maxTransactionLockRequestTimeoutMillis, the new transaction aborts.

In-progress Transactions and Write Conflicts

If a multi-document transaction is in progress and a write outside the transaction modifies a document that an operation in the transaction later tries to modify, the transaction aborts because of a write conflict.

If a multi-document transaction is in progress and has taken a lock to modify a document, when a write outside the transaction tries to modify the same document, the write waits until the transaction ends.

In-progress Transactions and Stale Reads

Read operations inside a transaction can return stale data. That is, read operations inside a transaction are not guaranteed to see writes performed by other committed transactions or non-transactional writes. For example, consider the following sequence: 1) a transaction is in-progress 2) a write outside the transaction deletes a document 3) a read operation inside the transaction is able to read the now-deleted document since the operation is using a snapshot from before the write.

To avoid stale reads inside transactions for a single document, you can use the db.collection.findOneAndUpdate() method. For example:

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

employeesCollection = session.getDatabase("hr").employees;

employeeDoc = employeesCollection.findOneAndUpdate(
   { _id: 1, employee: 1, status: "Active" },
   { $set: { employee: 1 } },
   { returnNewDocument: true }
  • If the employee document has changed outside the transaction, then the transaction aborts.
  • If the employee document has not changed, the transaction returns the document and locks the document.