Guide

A ticket platform looks like ordinary e-commerce until a popular tour goes on sale. Tens of thousands of seats meet millions of fans in the same minute. Browsing can be cached and slightly stale. Selling a seat cannot be. Seat 14C must belong to at most one buyer, even when the database is under a stampede, payments time out and bots hammer the API.

The design rests on two paths with different rules. The browse path (event pages, seat maps) is read-heavy and can be eventually consistent. The buy path (hold, pay, book) must be strongly consistent. Most of the design is about keeping the buy path small, fair and safe.

Requirements

  • Browse events, venues and seat maps.
  • Hold chosen seats for about 10 minutes while the user pays.
  • Finish with a paid ticket, or release the hold on timeout, cancel or payment failure.
  • Never double-book a seat, and stay fair to early arrivals.

The numbers

Demand / supply ≈ 2,000,000 people / 50,000 seats = 40 claimants per seat
If everyone polls the seat map once a second:  2M QPS of reads
A booking backend might handle roughly 5,000 to 20,000 holds/s
→ Admission must match that capacity, not the raw crowd

Reads dominate until a waiting room exists. Writes are fewer but hot, since every hold touches the same event's rows. Partition by event_id, so one hot show does not stall unrelated shows.

Concepts in this topic

StepConceptWhat it answers
1Check-then-act racesWhy does reading a seat and then writing it lose seats?
2Timed holds and lazy expiryHow does a claim expire without a cleanup job?
3Virtual waiting roomHow do you let in a crowd at a rate the system can handle?
4Authorize, commit, captureIn what order do you charge a card and claim a seat?

High-level design

Catalog and seat maps are cacheable. The hold service is the contention gate: only admitted clients reach it, and it claims seats atomically with a timeout. Checkout turns a valid hold into a sale once payment is authorized.

Read path

DataStaleness OK?Strategy
Event details, venueMinutesCDN and Redis with a long TTL
Seat coloursSecondsShort TTL, or push updates
"Your hold"NoAlways from the hold service

A seat that shows green for a few seconds after someone else held it is acceptable, as long as the hold API still refuses the claim. Showing a sold seat as bookable is not.

Multi-seat holds

A party of four needs four seats together. Partial success leaves orphaned seats. Claim all seats in one statement and require the row count to match. On any mismatch, roll back the whole hold and ask the client to refresh the map.

Bots and fairness

  • Only holders of a signed admission token reach the hold path.
  • Rate-limit holds per user, device and IP.
  • Watch for anomalies, such as a whole front row grabbed in 50 ms.

Fairness is a product policy. Engineering can enforce it only if tokens cannot be forged and holds expire.

Failure modes

FailureMitigation
Hold service downFail closed on writes; keep browsing up from cache
Redis flushedThe database hold_until is the source of truth; clients re-hold
Payment result unknownIdempotent payment intents and reconciliation
Over-admissionFeedback control on the waiting room rate

Common mistakes

  • Locking rows while a payment call is in flight. Waiters pile up behind a slow provider.
  • Charging before the seat is committed. A buyer who loses the seat then needs a refund.
  • Treating the cache as the record of sold seats. Only the strongly consistent path decides ownership.
  • Adding bot defenses after launch. They are much harder to add mid-sale.

Key takeaways

  • Unique seats need a strong commit path. Caches serve maps, not ownership.
  • Holds expire on their own. Check expiry at claim time.
  • A conditional update and a unique constraint on sold seats prevent double-booking.
  • A virtual waiting room matches demand to what the backend can sustain.
  • Payment is a saga: authorize, commit the seat, then capture.

Further learning

A full Ticketmaster-style interview walkthrough with an ex-Meta staff engineer. It shows how the waiting room and hold API get drawn under time pressure.

System Design Interview: Design Ticketmaster w/ a Ex-Meta Staff EngineerHello Interview
Hello Interview: Design TicketmasterDesigning a ticket booking system like Ticketmaster: the high-demand seat-reservation race, holds and expiry, a virtual waiting queue, and consistency.hellointerview.com

Transactions and isolation

Distributed transactions

Case study: payment system