
An order can be saved successfully while the message that tells another system about it fails. If the application writes to a database and publishes a message as two separate operations, a crash between them can leave the systems out of sync. The transactional outbox pattern records the business change and the intent to publish an event together.
The key boundary is the database transaction. The order and its outbox record are committed together, or neither is committed. A separate relay later publishes committed records to the messaging system. This removes the gap between saving the order and recording what needs to be sent, while leaving delivery and downstream processing as separate responsibilities.
How The Outbox Works
A transaction updates the business table and inserts an event record in an outbox table within the same database. The event has a stable identifier and enough information for the receiving workflow. Once the transaction commits, a relay reads pending records and attempts to publish them.

Imagine a hypothetical order service that needs to notify a shipping system. The order and an order created event are saved in one transaction. If the application stops after the commit, the event record remains available for the relay when processing resumes. If the transaction rolls back, neither the order nor the event is visible as a committed change.
The relay may poll the outbox or use a database change stream, depending on the infrastructure. Either approach needs a clear rule for recording progress and handling failures. The pattern does not require a particular broker, and delivery is not necessarily immediate.
Expect Duplicate Delivery
The relay can publish an event and then fail before recording that publication. On recovery it may send the same event again. Consumers must recognize the stable event identifier and handle repeated delivery safely. For a database update, this can involve recording processed identifiers with the resulting change in a transaction where the system supports it.
If a consumer calls an external service, its own database record may not be enough to prevent a duplicate side effect. Use the external service's idempotency support, verify the outcome or reconcile uncertain requests. Do not promise exactly-once business effects merely because an outbox exists.
Decide How Ordering And Recovery Work
Some workflows require events for the same order to be processed in sequence. Define which events need ordering and how the relay and consumer preserve or check it. Global ordering across every event may be unnecessary and costly. Handle an event that arrives after a newer state without silently reversing the result.
Monitor the age and number of pending records, publication failures and records that repeatedly fail. Establish who investigates a stuck event and how it is replayed or moved to a controlled failure queue. Set retention and cleanup rules that do not remove evidence before it is no longer needed.
Test The Gaps
Simulate a rollback before commit, a process crash after commit and a publish that succeeds before the relay records completion. Verify that no committed order loses its event and that a duplicate does not repeat the downstream effect. Test a consumer outage, ordering assumptions and recovery from invalid event data.
The event-driven agents guide describes what can happen after an event reaches an agent. The outbox solves an earlier, narrower problem: recording the business change and the intention to publish together.

