CHAPTER 23
Design Ticket Booking and Payments
Preventing double-booking, handling flash-sale spikes and getting money movement right
Source: PDF p. 61
| Functional requirements | Non-functional requirements and scale |
|---|---|
| - Browse events and seat maps; select seats - Hold seats for ~10 minutes during checkout - Pay securely; receive confirmation; refunds - Never sell the same seat twice | - Strong consistency for inventory and payments - Flash sales: 500 k users competing for 20 k seats within minutes - Idempotent, auditable payment flow - Browsing is read-heavy (cache/CDN) while booking is write-contended |
Deep dives p. 61
1. Never sell a seat twice Treat each seat as a row with a tiny state machine and change state with an atomic conditional update; the database arbitrates races, so no application locking is needed:
UPDATE seats p. 61
SET status = 'HELD', hold_id = :hold, hold_expires_at = now() + interval '10 minutes' WHERE seat_id = :seat AND (status = 'AVAILABLE' OR (status = 'HELD' AND hold_expires_at < now())); -- rows_affected = 1 => you got the seat; 0 => someone else did, pick another
- Confirming payment moves HELD -> SOLD only if hold_id still matches; a late payment for an expired hold triggers an automatic refund.
- For contended hot rows use a short Redis hold (SET seat:42 hold NX EX 600) as a fast pre-filter, but keep the database as the source of truth. Shard inventory by event/section so a huge event does not become a single hot partition.
Review questions for this chapter have not been written and reviewed yet. The chapter text above is the full source content.
Try it
References
System Design & AI System Design: The Complete Guide — 2026 Edition, p. 61; figures 44.
Tip: use ← and → keys to move between chapters.