Design Ticketmaster (Event Booking)
Sell a fixed set of seats to a crowd without ever double-booking.
Asked at Amazon, Microsoft and 2 more
3 min readยท8 sections
Ticketmaster sells a fixed number of seats for each event. Most of the time traffic is calm, then a popular concert goes on sale and millions of people try to buy the same 50,000 seats in the same minute. The design must never sell a seat twice, stay fair, and survive that spike.
Requirements#
Functional
- Browse events and see seat maps with live availability.
- Choose seats, hold them for a few minutes, then pay.
- Receive a ticket once payment succeeds.
Non-functional
- No double booking, ever. This is the one hard correctness rule.
- Handle sale spikes of millions of concurrent users for a single event.
- Seat maps can be a few seconds stale; the final booking cannot.
Booking flow#
- The user selects seats.
- The system reserves them for 10 minutes so nobody else can take them.
- The user pays.
- On success, the reservation becomes a confirmed booking. If the timer runs out, the seats are released.
Data model#
seats (
event_id BIGINT,
seat_id VARCHAR(10),
status VARCHAR(10), -- available | held | booked
hold_id UUID,
held_until TIMESTAMP,
PRIMARY KEY (event_id, seat_id)
);Reserving seats safely#
Two people clicking the same seat at the same moment must not both get it. A conditional update makes the reservation atomic:
UPDATE seats
SET status = 'held', hold_id = :hold, held_until = now() + interval '10 minutes'
WHERE event_id = :event AND seat_id IN (:seats)
AND (status = 'available' OR (status = 'held' AND held_until < now()));
-- Succeeds only if every requested seat was updated; otherwise roll backThis is optimistic: no locks are held while the user browses, and the database row is the single source of truth. A Redis lock per seat with a TTL is a faster alternative for the hold, as long as the final booking is still checked in the database.
Architecture#
Surviving the on-sale spike#
- Virtual waiting room: instead of letting everyone hit the booking service, users join a queue and are let in at a rate the system can handle, each with a signed token. It's fairer too: a random position or first-come order instead of whoever retries fastest.
- Static content at the edge: event pages, images and seat map layouts come from the CDN.
- Cached availability: the seat map shows availability from a cache refreshed every second or two. Being slightly stale is fine because the reservation query is the real check.
- Per-event isolation: a mega on-sale event can get dedicated capacity so other events keep working.
Payments and timeouts#
Payment providers can be slow. The hold timer gives the user time to pay; the booking service calls the payment service with an idempotency key tied to the hold, so retries never charge twice. If payment fails or the hold expires, the seats go back to available.
Bots and fairness#
Bots buy tickets to resell them. Countermeasures include the waiting room, per-account and per-card purchase limits, CAPTCHA at entry, and verified fan programs that issue access codes ahead of the sale.
Finished this walkthrough?
Mark it as read to track your progress in the list.