The outbox pattern

The dual-write problem

A booking gets created and, in the same breath, you want to tell the rest of the system: publish a "booking_created" event to Redis so other consumers (analytics, the walker's mobile push notification, a partner webhook) can react. That's two separate writes โ€” one to Postgres (the booking row), one to Redis (the event) โ€” and they can't be wrapped in one atomic transaction, because Postgres and Redis are two different systems with no shared commit.

Whichever order you pick, there's a failure mode that loses correctness:

  • Publish first, commit second. The publish to Redis succeeds, consumers start reacting to "booking_created" โ€” then the database transaction fails or gets rolled back. Now the rest of the system believes a booking exists that was never actually saved. A ghost event.
  • Commit first, publish second. The database transaction commits โ€” the booking is real. Then the process crashes, or the Redis call fails, right before the publish. The booking exists, but nobody downstream ever hears about it. A lost event.