Error
Error Code: 112

MongoDB Error 112: Concurrent Document Modification

📦 MongoDB
📋

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 causes
⚠️
Multiple 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 available

1. 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
}
🔗

Related Errors

5 related errors