Events and messaging

3 min read ·

Transactional Outbox: The Order Was Saved, but the Event Disappeared

Checkout succeeded, but the warehouse never received the order. How to close a small but dangerous gap between the database and the message broker.

The customer places an order and sees a confirmation. The warehouse never receives the work. The order service is running; its database contains the order. The event simply did not reach the other systems. Each component may even be reporting healthy status.

The failure lives between two distinct operations: committing a business change and publishing a message. An application can crash in between. Transactional Outbox is designed to stop that small technical gap from becoming a broken promise to the customer.

Two successful calls are not one atomic action

Suppose the service saves an order first and publishes its event second. If the database commit succeeds but the application crashes before publishing, the warehouse never learns about it. Reversing the order does not solve the problem: the event may be published, then the database transaction may fail, leaving downstream systems reacting to an order that does not exist.

Running both calls in sequence is not enough. We need the business change and the durable intention to notify others to succeed or fail together.

Put the intention in the same transaction

The application writes the order and an outbox record within one local database transaction. That record describes the message that must eventually be delivered. Once the transaction commits, a separate relay publishes pending records to the broker.

The relay may poll the outbox or follow the database transaction log. If the broker is temporarily unavailable, the record remains and can be sent later. The broker and database do not become one transactional platform; the durable intent to publish is what shares a transaction with the order.

That distinction matters. Outbox solves a specific gap without pretending the whole distributed workflow is one atomic transaction.

Reliable publication does not mean exactly-once processing

Imagine the relay sends a message successfully, then crashes before recording that publication is complete. After restart, it may publish the same record again. The system is recovering from an uncertain outcome, and duplicate delivery is a normal possibility.

The consumer must therefore make repeated processing safe. If an event awards loyalty points or starts fulfilment, it needs a stable event or operation identity and a way to recognise that the business effect has already happened.

Ordering requires thought as well. If the same order moves through multiple states, parallel relay processes should not silently destroy a business-relevant sequence. Partition keys, sequence numbers and transport-specific guarantees all have limits.

How do you notice that delivery has stopped?

The pattern may be correctly implemented while the operation is still unmanageable. Messages stop publishing, the outbox grows, and nobody knows how many orders are waiting. Monitoring should therefore include the age of the oldest unpublished event, failed attempts, publication lag and consumer progress.

Teams also need rules for cleaning up successfully sent records, replaying failures and recovering after long outages. For processes involving payments or fulfilment, somebody must be able to explain which customer obligations remain unfinished.

When not to introduce an outbox

If nothing crosses a system boundary and one local transaction already covers the operation, there may be no dual-write problem to solve. If the platform offers another form of atomic event publication, inspect its actual guarantees before adding a second mechanism.

Outbox is useful when a lost notification about a committed business fact would break an important workflow.

It helps prevent missing events; it does not remove duplicates or the need for operational ownership. “Published reliably” is still not the same as “processed exactly once”.

The Transactional Outbox pattern and AWS Prescriptive Guidance describe implementation options and their trade-offs.