mongodb-transactions

Master MongoDB ACID transactions for multi-document operations. Learn session management, transaction mechanics, error handling, and production patterns. Guarantee data consistency across multiple operations.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "mongodb-transactions" with this command: npx skills add pluginagentmarketplace/custom-plugin-mongodb/pluginagentmarketplace-custom-plugin-mongodb-mongodb-transactions

MongoDB Multi-Document Transactions

Guarantee consistency with ACID transactions across multiple operations.

Quick Start

Basic Transaction

const session = client.startSession()

try {
  await session.withTransaction(async () => {
    // All operations here are atomic
    await users.insertOne({ name: 'John' }, { session })
    await accounts.insertOne({ userId: 'xxx', balance: 100 }, { session })

    // If any fails, ALL roll back
  })
} catch (error) {
  console.error('Transaction failed:', error)
} finally {
  await session.endSession()
}

Real-World: Money Transfer

async function transferMoney(fromId, toId, amount) {
  const session = client.startSession()

  try {
    await session.withTransaction(async () => {
      // Deduct from account A
      await accounts.updateOne(
        { _id: fromId },
        { $inc: { balance: -amount } },
        { session }
      )

      // Add to account B
      await accounts.updateOne(
        { _id: toId },
        { $inc: { balance: amount } },
        { session }
      )

      // Both succeed, or both rollback - NO PARTIAL TRANSFERS!
    })
  } catch (error) {
    // Transaction failed, money not transferred
    console.error('Transfer failed:', error)
  } finally {
    await session.endSession()
  }
}

Transaction Requirements

MongoDB Version

  • MongoDB 4.0+: Single-document transactions (all versions)
  • MongoDB 4.0: Multi-document transactions (replica sets)
  • MongoDB 4.2+: Multi-document transactions (sharded clusters)

Deployment Type

  • Replica Set: Required for transactions
  • Sharded Cluster: MongoDB 4.2+
  • Standalone: Single-document transactions only
  • Atlas Free: No transactions (shared clusters)

Session Management

Create Session

const session = client.startSession()

// Configure session
const session = client.startSession({
  defaultTransactionOptions: {
    readConcern: { level: 'snapshot' },
    writeConcern: { w: 'majority' },
    readPreference: 'primary'
  }
})

Session Lifecycle

// 1. Start session
const session = client.startSession()

// 2. Start transaction
session.startTransaction()

// 3. Execute operations with session
await collection.insertOne(doc, { session })

// 4. Commit or abort
await session.commitTransaction()  // Success
await session.abortTransaction()   // Rollback

// 5. End session
await session.endSession()

Transaction Options

Read Concern

// snapshot: See committed data at transaction start
// local: See latest data (default)
// majority: See data confirmed on majority
// linearizable: Latest confirmed data

await session.withTransaction(async () => {
  // Operations
}, {
  readConcern: { level: 'snapshot' }
})

Write Concern

// w: 1 (default): Acknowledged by primary
// w: 'majority': Acknowledged by majority
// w: N: Acknowledged by N replicas

await session.withTransaction(async () => {
  // Operations
}, {
  writeConcern: { w: 'majority' }
})

Read Preference

// primary: Read from primary only
// primaryPreferred: Primary, fallback to secondary
// secondary: Read from secondary
// secondaryPreferred: Secondary, fallback to primary
// nearest: Nearest server

{
  readPreference: 'primary'
}

Error Handling

Handle Transaction Errors

async function robustTransaction() {
  const session = client.startSession()

  try {
    await session.withTransaction(async () => {
      // Operations
    })
  } catch (error) {
    if (error.hasErrorLabel('TransientTransactionError')) {
      // Temporary error - retry
      return robustTransaction()
    } else if (error.hasErrorLabel('UnknownTransactionCommitResult')) {
      // Commit outcome unknown - check state
      console.log('Commit outcome unknown')
    } else {
      // Fatal error
      throw error
    }
  } finally {
    await session.endSession()
  }
}

Retry Logic

async function executeWithRetry(fn, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    const session = client.startSession()

    try {
      await session.withTransaction(async () => {
        await fn(session)
      })
      return  // Success
    } catch (error) {
      if (error.hasErrorLabel('TransientTransactionError') && attempt < maxRetries) {
        continue  // Retry
      } else {
        throw error
      }
    } finally {
      await session.endSession()
    }
  }
}

Real-World Examples

Order Placement with Inventory

async function placeOrder(userId, items) {
  const session = client.startSession()

  try {
    await session.withTransaction(async () => {
      // 1. Create order
      const order = {
        userId,
        items,
        status: 'pending',
        createdAt: new Date()
      }
      const orderResult = await orders.insertOne(order, { session })

      // 2. Update inventory
      for (const item of items) {
        const updated = await products.findOneAndUpdate(
          { _id: item.productId },
          { $inc: { stock: -item.quantity } },
          { session, returnDocument: 'after' }
        )

        // Check if stock went negative
        if (updated.value.stock < 0) {
          throw new Error('Insufficient inventory')
        }
      }

      // 3. Deduct from user account
      const userUpdate = await users.findOneAndUpdate(
        { _id: userId },
        { $inc: { balance: -calculateTotal(items) } },
        { session, returnDocument: 'after' }
      )

      if (userUpdate.value.balance < 0) {
        throw new Error('Insufficient funds')
      }

      return orderResult.insertedId
    })
  } catch (error) {
    // ALL operations rolled back if any fails
    // Inventory stays same
    // User balance unchanged
    // Order not created
    console.error('Order failed:', error.message)
    throw error
  } finally {
    await session.endSession()
  }
}

Account Reconciliation

async function reconcileAccounts(mainId, secondaryIds) {
  const session = client.startSession()

  try {
    await session.withTransaction(async () => {
      // Calculate total balance
      const secondary = await accounts.find(
        { _id: { $in: secondaryIds } },
        { session }
      ).toArray()
      const totalBalance = secondary.reduce((sum, acc) => sum + acc.balance, 0)

      // Update main account
      await accounts.updateOne(
        { _id: mainId },
        { $set: { balance: totalBalance } },
        { session }
      )

      // Delete secondary accounts
      await accounts.deleteMany(
        { _id: { $in: secondaryIds } },
        { session }
      )

      // Log reconciliation
      await reconciliationLog.insertOne({
        mainId,
        secondaryIds,
        totalBalance,
        timestamp: new Date()
      }, { session })

      // All succeed together, or all rollback
    })
  } finally {
    await session.endSession()
  }
}

Limitations & Considerations

Transaction Limits

- Maximum 16MB of write operations
- Cannot create/drop collections
- Cannot create/drop indexes
- Cannot alter collections
- Cannot write to system collections

Performance Impact

- Transactions have overhead
- Write operations slower (more coordination)
- Locking increases lock contention
- Not for every operation

Best Practices

Transaction Best Practices:

  1. Keep short - Minimize lock time
  2. Retry transient errors - Network issues happen
  3. Order operations - Prevent deadlocks
  4. Use appropriate write concern - 'majority' for safety
  5. Monitor latency - Transactions add overhead

When to Use:

  1. ✅ Money transfers
  2. ✅ Order processing
  3. ✅ Inventory management
  4. ✅ Account operations
  5. ✅ Any multi-collection atomic operations

When NOT to Use:

  1. ❌ Single document operations (inherently atomic)
  2. ❌ Simple inserts/updates
  3. ❌ Performance-critical reads
  4. ❌ Batch operations (use bulk)
  5. ❌ If not on replica set

Next Steps

  1. Learn session basics - StartSession, endSession
  2. Write simple transaction - Insert and update
  3. Add error handling - Try-catch blocks
  4. Implement retry logic - Handle transient errors
  5. Monitor performance - Measure transaction time

Guarantee consistency with transactions!

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

mongodb-aggregation-pipeline

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

mongodb-indexing-optimization

No summary provided by upstream source.

Repository SourceNeeds Review
Security

mongodb-security-admin

No summary provided by upstream source.

Repository SourceNeeds Review