Examples/Ticketing
Concert ticketing (example)
Concert ticket sales with seat maps, 10-minute seat holds during checkout, and a waiting room in front of the API for on-sale spikes. Postgres holds seat state, a queue feeds ticket issuing, and an object store keeps the ticket PDFs.
Scale: 100k buyers in the first minute of an on-sale; 20k seats per show
Select a component to see what it is responsible for and which state it owns.
- 1Buyer web and app → Waiting room: Join queue
- 2Buyer web and app → CDN: Load event page
- 3Buyer web and app → Ticketing API: View seats
- 4Ticketing API → Seat availability cache: Read availability
- 5Ticketing API → Postgres: Hold seats
- 6Ticketing API → Payment provider: Pay
- 7Payment provider → Ticketing API: Payment webhook
- 8Ticketing API → Order queue: Order confirmed
- 9Ticket issuer → Order queue: Consume orders
- 10Ticket issuer → Ticket store: Store ticket
- 11Ticket issuer → Email provider: Email ticket
- 12Hold sweeper → Postgres: Release expired holds
- Request / response
- Asynchronous
- Bulk data
Select a part to trace its flows.
- Request / response
- Asynchronous
- Bulk data
Parts 12
Flows 12
- 1Buyer web and app → Waiting roomJoin queueRequest / response
- 2Buyer web and app → CDNLoad event pageRequest / response
- 3Buyer web and app → Ticketing APIView seatsRequest / response
- 4Ticketing API → Seat availability cacheRead availabilityRequest / response
- 5Ticketing API → PostgresHold seatsRequest / response
- 6Ticketing API → Payment providerPayRequest / response
- 7Payment provider → Ticketing APIPayment webhookAsynchronous
- 8Ticketing API → Order queueOrder confirmedAsynchronous
- 9Ticket issuer → Order queueConsume ordersRequest / response
- 10Ticket issuer → Ticket storeStore ticketBulk data
- 11Ticket issuer → Email providerEmail ticketRequest / response
- 12Hold sweeper → PostgresRelease expired holdsRequest / response
Invariants 3
A seat is sold to one buyer
Conditional UPDATE on seats that takes only rows that are available or whose hold has expired; the transaction checks the row count and rolls back unless every requested seat was taken.
Kept by
A payment for an expired hold does not sell the seat
Conditional UPDATE from held to sold that matches the hold id and requires an unexpired hold; a zero row count sends the payment to a refund.
Kept by
The API sees at most the admitted rate
The waiting room issues signed admission tokens with an expiry at a fixed rate; the API rejects any request without a valid token.
Kept by