A seat-booking saga across three independently deployed services. No shared database, no distributed transaction — correctness comes from an outbox, idempotent consumers, and a Redis hold that only one booking can win.
Books the selected seat and follows the saga as it hops between services. Each event is written to an outbox in the same transaction as the state change, then published to Kafka — so nothing is lost if a service dies mid-flight.
Fires N booking requests for the same seat at the same instant. All of
them are accepted — the API is asynchronous, so every caller gets 201 PENDING.
One wins the Redis hold; the rest get SeatsRejected and cancel themselves.
This is the invariant the project exists to protect.
Unchecked, every client uses a declining card, so the winner’s hold is released and the seat stays bookable.