$ lexprog.com

// notes from an old coder -- php, databases, and the occasional rant

[October 12, 2026] MongoDB

MongoDB Outbox Pattern: Reliable Messaging

MongoDB Outbox Pattern: Reliable Messaging

────────────────────────────────────────────────────────

MongoDB Outbox Pattern: Reliable Messaging

Tip: Outbox Collection

$outbox->insertOne([
    'event_type' => 'order.created',
    'payload' => $orderData,
    'processed' => false,
    'created_at' => new UTCDateTime(),
]);

Gotcha: Transactional Outbox

Insert the outbox entry in the same transaction as the main data.

Tip: Polling Processor

$events = $outbox->find(['processed' => false])->sort(['created_at' => 1])->limit(100);

Gotcha: Duplicate Processing

The same event may be processed twice. Make consumers idempotent.

Tip: Mark as Processed

$outbox->updateOne(
    ['_id' => $eventId],
    ['$set' => ['processed' => true, 'processed_at' => new UTCDateTime()]]
);

Gotcha: Cleanup Old Events

Schedule deletion of processed events to prevent unbounded growth.

Tip: Embed or Reference? The 80/20 Rule

If you always access data together, embed it. If you access it independently, reference it. The 16MB document size limit is the hard boundary — stay under 1MB for most documents.

Tip: Index Your Query Patterns, Not All Fields

Creating indexes on every field wastes RAM. Use explain() to find in-memory sorts and collection scans. Index only what your actual queries filter on.

Gotcha: No Transaction Rollback for Index Builds

Building an index on a large collection can take hours. If it fails midway, the partial index is silently discarded. Plan index builds during maintenance windows.

Senior Insight

The outbox pattern ensures reliable message delivery by writing events to an 'outbox' collection within the same transaction as the business data change. A separate process reads the outbox and publishes events to a message broker. I've implemented this pattern for transactional email sending and cross-service event publication. The advantage: guaranteed delivery without distributed transactions. The complexity: you need an outbox processor that handles partial failures and deduplication.

Source: MongoDB Developer Center (https://www.mongodb.com/developer/), MongoDB Engineering Blog (https://www.mongodb.com/blog/channel/engineering-blog), Studio 3T Blog (https://studio3t.com/blog/)

────────────────────────────────────────────────────────
<-- back to posts