System Design · Architecture under constraints

What is the transactional outbox pattern and why is it needed?

Hardoutboxdual writechange data captureUpdated Oct 2026
Quiz this track

Short answer

The outbox pattern writes the state change and an event row in one database transaction, then relays the event. It removes the dual-write gap between committing data and publishing to a broker.

Publishing to a broker and committing to a database are two separate systems. If the commit succeeds and the publish fails, downstream consumers never see the event. If the publish succeeds and the commit fails, consumers act on something that never happened. The outbox removes this gap.

sql
BEGIN;

UPDATE orders
SET status = 'CONFIRMED'
WHERE id = 42 AND status = 'PENDING';

INSERT INTO outbox (id, aggregate_id, event_type, payload, created_at)
VALUES ('evt_01', 42, 'OrderConfirmed', '{"orderId":42}', now());

COMMIT;
The state change and the event record commit atomically. A separate relay publishes committed outbox rows.

How the relay works

  • Polling publisher: a worker selects unpublished rows, publishes them, then marks them sent
  • Change data capture: a log reader such as Debezium tails the database log and emits inserts
  • The relay must tolerate publishing twice, because marking sent can fail after a successful publish
  • Consumers must deduplicate by event id or make their effects idempotent
  • Ordering is preserved only if the relay publishes in commit order for a given aggregate

The outbox table grows and needs cleanup. Delete or archive rows after they are confirmed sent, but keep them long enough for replay and audit. If the relay is down, events accumulate in the database, which is a visible backlog rather than silent loss. That is the main advantage over a best-effort publish.

The outbox is at-least-once, not exactly-once. A crash between publishing and marking sent causes a duplicate. Deduplicate at the consumer, and use an event id that is stable across retries rather than generating a new id in the relay.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1Why can the outbox not guarantee exactly-once delivery?
  2. 2How do you preserve ordering per aggregate?
  3. 3What are the trade-offs of polling versus change data capture?
  4. 4How long would you retain outbox rows?

Say it in the interview

The outbox pattern writes the business change and an event row in the same local transaction, so they either both commit or both fail. A relay then publishes committed rows, using polling or change data capture. It guarantees at-least-once, not exactly-once, so consumers still need deduplication by a stable event id. The trade-off is a table to clean up and a backlog that lives in the database instead of being silently lost.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live System Design mock interview and get scored feedback on depth, clarity and confidence.