Part 7 · 1 chapters · ~8 min
Outbox and Inbox
The dual-write problem, the transactional outbox with polling and CDC relays, ordering and cleanup of outbox rows, the inbox pattern for idempotent consumption, combining both for end-to-end exactly-once effect, and libraries that implement them.
10
Both ends of a reliable message
code
-- outbox (producer side) BEGIN; UPDATE payouts SET state = 'completed' WHERE id = $1; INSERT INTO outbox (id, aggregate_id, type, payload) VALUES (gen_random_uuid(), $1, 'PayoutCompleted', $2); COMMIT; -- relay: SELECT ... FROM outbox WHERE published_at IS NULL ORDER BY created_at LIMIT 100 FOR UPDATE SKIP LOCKED; publish; mark published -- inbox (consumer side) BEGIN; INSERT INTO inbox (message_id) VALUES ($msg_id) ON CONFLICT DO NOTHING; -- 0 rows → duplicate, skip the effect UPDATE loyalty_points SET points = points + 10 WHERE user_id = $u; COMMIT; -- then acknowledge
OUTBOX AND INBOX
reliable publishing out, reliable processing in
swipe the figure sideways, or tap expand for full screen
1/4
the outbox
Writing state and publishing an event are two systems with no shared transaction (the dual-write problem). The outbox writes the event as a row in the same transaction as the state (Scaling course P7).
event row in the state transactionno dual write