Skip to main content
HS
HiSETSuccess
LeetCode Prep

System Design

Interview framework, chapters, case studies, depth guides, and adaptive quizzes.

Case study

Design Ticketmaster Event Booking

Sell concert tickets fairly under extreme flash-sale load without overselling or double-booking seats.

concurrencyinventoryqueue

Requirements

  • Functional: browse events; select seats; hold during checkout; purchase; e-ticket
  • Prevent double booking of same seat
  • Queue users during high-demand onsales (1M users, 10K seats)
  • Non-functional: hold TTL 10 min; purchase idempotent; 99.99% inventory accuracy
  • Scale: 50K concurrent checkout sessions during mega onsale

Back-of-envelope Estimation

MetricCalculationResult
Flash sale1M users, 10K seats100:1 oversubscription
Peak RPS1M enter queue in 1 min~17K/sec gate traffic
Seat hold writes50K concurrent × 4 seats avg200K held seats max
Inventory readsEvery seat map poll ~1/sec/userCDN + cache critical

API Design

EndpointDescription
GET /v1/events/{id}/seatsSeat map with availability (cached)
POST /v1/holds{ eventId, seatIds[] } → { holdId, expiresAt }
POST /v1/orders{ holdId, paymentToken, idempotencyKey } → order
GET /v1/queue/{eventId}/statusVirtual waiting room position

Data Model

EntityFields
seatsevent_id, seat_id, section, row, status(available|held|sold), version
holdshold_id, user_id, seat_ids[], expires_at, status
ordersorder_id, hold_id, payment_id, status, created_at
waiting_roomevent_id, user_id, queue_token, position — Redis

High-level Design

Flash sale flow
User ──► Waiting Room (token bucket admit N/sec)
              └──► Seat Map (CDN cached static layout + Redis availability overlay)
              └──► Hold Service ──► optimistic lock seat rows (version column)
              └──► Checkout ──► Payment ──► confirm seats SOLD (atomic)

Deep Dive: Seat Hold with Optimistic Locking

UPDATE seats SET status='held', version=version+1 WHERE seat_id IN (...) AND status='available' AND version=@expected. If row count < requested, rollback and return 409. Hold expires via TTL job releasing seats.

Why not pessimistic lock

SELECT FOR UPDATE on 10K rows serializes the sale. Optimistic concurrency with version column scales; retry on conflict for alternate seats.

Deep Dive: Virtual Waiting Room

  • Admit 500 users/sec from FIFO queue to prevent origin meltdown
  • Queue token in cookie; random shuffle prevents bot front-running
  • Bots: device fingerprint + proof-of-work challenge before queue entry
  • Grace period if user refreshes — token tied to session

Failure Modes & Monitoring

SLOTarget
Inventory accuracy100% — zero oversell
Hold expiry enforcement< 30 sec after TTL
Queue admit rateStable under configured cap

Reconciliation job compares sold seats vs payment records nightly. Alert on any seat with status=sold without matching order.

Attempt the case aloud first. Then unlock a staff model answer outline.