System Design Arena
Design Ticketmaster
Event ticketing under extreme contention: browse events, hold seats, pay — without double-selling seat 14B when a superstar tour goes on sale.
Case Study
Ticketmaster
Same conversation, diagrams, and wrap-up you expect—now framed with clearer scaffolding and iconography.
Prompt
Design a ticketing service like Ticketmaster where users browse events, select specific seats, and purchase them — including a Taylor-Swift-scale on-sale.
Interview snapshot
- • Topic: Ticketmaster
- • Expected depth: 45 - 60 minutes
- • Focus areas: APIs, scale estimation, resilient architecture
- • Wrap-up: risk, monitoring, disaster recovery
Key takeaways
- • Browse events and interactive seat maps.
- • Zero double-sells — correctness beats availability on the purchase path.
- • GET /events/{id}/seats → seat map + advisory availability bitmap.
🎙️ Interview mode
Practice this like a real interview
Don't read the answer first. Work the framework against the bare prompt, then compare against what the interviewer expected at each step.
Scorecard
What the interviewer is evaluating
Staff-level signal
Does the candidate recognize this as a CONTENTION problem (10M people, 50K seats) and reach for holds + a waiting room instead of "more servers"?
🧠 Staff engineer judgment
Autoscaling cannot fix contention on 50K seat rows. When the resource itself is scarce, admission control (a waiting room) beats capacity every time.
Calibration
The common (bad) answer
User → LB → App servers (autoscaled ×100) → Seats table SELECT … WHERE available=true; UPDATE …
❌ Why this scores poorly: The check-then-update race double-sells seats the moment two requests interleave — and autoscaling multiplies the racers, making it worse.
✓ What a strong answer adds
- Atomic compare-and-set per seat: available → held(session, TTL) in one operation.
- Holds with TTL and an explicit state machine: available → held → sold.
- A virtual waiting room that admits users at the rate the hold path can absorb.
- Advisory (cached) availability for browsing; transactional truth only at hold time.
- Idempotent payment completion keyed by holdId.
Video walkthrough
System Design Interview: Design Ticketmaster
Hello Interview · ex-Meta staff engineer · 58 min
Seat reservation under contention: locking, holds and the thundering-herd problem.
Work the prompt yourself first — guided practice grades your own answer step by step. Watching someone else design it feels like progress and teaches you far less.
Interview flow
Dialogue timeline
Interviewer
What are we building?
Candidate
Event browsing and seat maps, temporary seat holds while a user checks out, and purchase. The invariant that beats everything else: a seat is never sold twice.
Interviewer
What's the scale and shape of the load?
Candidate
Browsing is ordinary read traffic. The interesting shape is the on-sale spike: 10M users contending for 50K seats in minutes. It's a contention problem wearing a scale costume.
Interviewer
How do you keep browsing fast during a spike?
Candidate
Event and seat-map data is read-heavy and cache-friendly — CDN and Redis with seat availability as a slightly-stale bitmap. Availability shown during browse is advisory; truth lives only in the hold/purchase path.
Interviewer
Walk me through selecting a seat.
Candidate
Selecting creates a hold: an atomic conditional write on the seat row — 'available → held by session X, expires in 10 min'. Postgres row-level locking or Redis with Lua both work; the key is one atomic compare-and-set, one owner.
Interviewer
Two users click seat 14B in the same millisecond.
Candidate
One CAS wins, one loses and instantly sees 'seat taken — here are neighbors'. The loser must fail fast; a queued or slow failure is what melts systems and users' trust.
Interviewer
Holds expire how?
Candidate
TTL on the hold; expiry returns the seat to the pool. Payment completion converts hold→sold in a transaction that verifies the hold still belongs to that session. Crash between payment and conversion is reconciled by an idempotent payment-callback replay.
Interviewer
The on-sale starts and 10M people arrive. What protects the seat store?
Candidate
A virtual waiting room: admit users in randomized batches with signed tokens, sized to what the hold path can absorb. Everyone else sees a queue position. It converts a stampede into a steady stream — fairness plus survival.
Interviewer
Why not just autoscale instead of a queue?
Candidate
The bottleneck is per-seat contention, not compute — 10M CAS attempts on 50K rows serialize regardless of how many app servers you add. Autoscaling multiplies the mob; the waiting room shrinks it.
Scoping
Requirements & trade-offs
Functional Requirements
- —Browse events and interactive seat maps.
- —Hold specific seats for ~10 minutes while checking out.
- —Purchase converts hold to owned ticket; holds expire back to the pool.
- —Out of scope: resale marketplace, dynamic pricing, fraud.
Non-Functional Requirements
- —Zero double-sells — correctness beats availability on the purchase path.
- —Survive 100× normal traffic during on-sales without collapsing browse.
- —Hold acquisition responds in <500ms — win or lose fast.
- —Fairness: on-sale access order shouldn't reward better bots.
Blueprint
Architecture modules
Module 1
API Endpoints
- •GET /events/{id}/seats → seat map + advisory availability bitmap.
- •POST /holds {eventId, seatIds[]} → {holdId, expiresAt} or 409 with alternatives.
- •POST /purchase {holdId, paymentToken} — idempotent by holdId.
- •Waiting room issues signed admission tokens required by /holds during on-sales.
Module 2
Back-of-the-Envelope
- •50K seats, 10M interested → 200:1 oversubscription; most users must never reach the seat store.
- •Hold path sized at ~5K holds/sec → admit ~5K users/sec from the queue.
- •Seat state is tiny (50K rows/event) — contention, not volume, is the enemy.
- •Browse spike ~1M RPS handled almost entirely by CDN + cache.
Module 3
System Diagram Notes
- •CDN → Browse services (cached seat bitmaps) — fully separate from the transactional path.
- •Waiting room (queue + token issuer) gates the Hold service.
- •Hold service → Seat store (partitioned by event; atomic CAS per seat).
- •Payment service converts holds; callbacks are idempotent.
Module 4
Design Playbook
- •Name the invariant first: no seat sold twice — it justifies every later choice.
- •Split advisory availability (cacheable) from transactional truth (locked).
- •Holds with TTL are the heart; show the state machine available→held→sold.
- •Introduce the waiting room as a contention valve, not a scaling hack.
- •Explain why the loser of a seat race must fail in milliseconds.