Patterns

Transactional outbox

Write the event in the same database transaction as the change, then publish it from there, so the database and the broker never disagree.

The transactional outbox makes "save the order and announce it" one atomic step.

Use it when#

  • A change in your database must also produce a message, such as OrderPlaced.

  • Losing the message or sending a message for a rolled-back change would corrupt another service.

How it works#

The naive code saves the row, then publishes to the broker. If the process dies between the two, the row exists and no one hears about it. Swap the order and a failed save leaves a message about nothing. The two systems cannot share one transaction.

So the app inserts the event into an outbox table inside the same transaction as the order. A relay process reads new outbox rows and publishes them, then marks them sent. A crash after publishing and before marking sends the event twice, so consumers must handle duplicates.

one transactionAppOrders + OutboxRelayBroker

What it costs#

Events arrive a little later than the commit, because the relay polls or tails the log. You run and watch one more process, and the outbox table needs cleanup. Delivery is at-least-once, so idempotent consumers are required.

In Quorum#

Drag to pan. Hold Ctrl or Cmd and scroll to zoom.

At 800 Users the Simulation solves this Design to Apdex 1.00, p99 213 ms, 0.0% errors and $13/s Burn.
WhereSettingValueWhy
App ServerInstance sizemediumMedium, so the App Server is not the limit.
DatabaseInstance sizemediumMedium. It holds the rows and the outbox.
Realtime HubStacknodeAn event loop holds each open connection for a few KB, where the default Stack holds a worker for each.
Realtime HubClusteringOnWithout it one box takes every connection.

Research this Design needs: Full-text search, Checkout, Hosted models, WebSockets, Object storage, WebSockets, Message queues, Full-text search, Transactional outbox.

The other Nodes in the picture only serve the other request kinds of Series B, such as checkouts and realtime. Research Transactional outbox and the game stops counting the dual-write loss: from Series B, a share of search answers is stale when the app writes to the Database and the Search Engine separately and nothing carries the change. The outbox is a Research, not a Node, so the Design shows only its effect and has no setting of its own. A CDC Connector removes the same loss by reading the Database log, which Change data capture covers. The glossary defines the transactional outbox.