Error
Error Code:
112
MongoDB Error 112: Concurrent Document Modification
Description
Error 112, 'Write Conflict', indicates that a write operation failed because another concurrent write operation modified the same document or index entry. This typically occurs in highly concurrent environments where multiple clients attempt to update the same data simultaneously, leading to an optimistic locking failure.
Error Message
Write Conflict
Known Causes
3 known causesMultiple Writes to Same Document
Several concurrent write operations attempt to modify the exact same document or a small set of 'hot' documents simultaneously.
Conflicting Index Updates
Concurrent operations modify documents in a way that affects the same index key, leading to a conflict during index maintenance.
Overlapping Transaction Writes
Two or more multi-document transactions attempt to write to the same document or index entry, violating isolation guarantees.
Solutions
4 solutions available1. Retry the Operation easy
Write conflicts are transient - retry
1
Implement retry logic
async function updateWithRetry(filter, update, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await db.collection.updateOne(filter, update);
} catch (err) {
if (err.code === 112 && i < maxRetries - 1) {
await sleep(100 * Math.pow(2, i)); // Exponential backoff
continue;
}
throw err;
}
}
}
2. Use findOneAndUpdate easy
Atomic operation reduces conflicts
1
Use atomic operation
db.accounts.findOneAndUpdate(
{ _id: accountId, version: currentVersion },
{ $set: { balance: newBalance }, $inc: { version: 1 } },
{ returnNewDocument: true }
);
3. Reduce Transaction Scope medium
Smaller transactions have fewer conflicts
1
Keep transactions short
// Bad: Long transaction
const session = client.startSession();
const account = await coll.findOne({ _id: id }, { session });
// ... long processing ...
await coll.updateOne({ _id: id }, { $set: {...} }, { session });
await session.commitTransaction();
// Good: Minimize transaction scope
const account = await coll.findOne({ _id: id }); // Outside transaction
// ... processing ...
const session = client.startSession();
await coll.updateOne({ _id: id }, { $set: {...} }, { session });
await session.commitTransaction();
4. Use Optimistic Concurrency medium
Version field to detect conflicts
1
Add version field
// Include version in query
const result = await db.items.updateOne(
{ _id: itemId, version: doc.version },
{
$set: { data: newData },
$inc: { version: 1 }
}
);
if (result.modifiedCount === 0) {
// Someone else updated - reload and retry
}