01What must users do — browse and search events, or is this booking-only?
Users can view an event with its venue seat map and near-real-time availability, and search events by keyword, date, and location.
Free full guide
Design Ticketmaster — an event ticketing system that sells reserved seats under extreme flash-sale contention without ever double-selling a seat.
The interview rhythm stays compact, so the page can spend attention on the actual design decisions.
Do not only state requirements. Ask for them. Each card pairs the design constraint with a clarification question you can say out loud before drawing the architecture.
01What must users do — browse and search events, or is this booking-only?
Users can view an event with its venue seat map and near-real-time availability, and search events by keyword, date, and location.
02When a user picks seats, do they get a temporary hold while they pay?
Users can select seats and get a short-lived hold (5-10 minutes): reserve first, then confirm with payment; an unconfirmed hold auto-releases.
03What is the one guarantee we can never break?
A booking is final: each seat sells exactly once — no double-booking, ever, even during a flash on-sale.
04Seat-map selection, best-available allocation, or both?
Both: map selection for reserved venues and best-available - and best-available still takes atomic holds on concrete seats, never a vague count.
05Can a buyer add seats to an existing hold mid-checkout?
Yes while the hold lives: added seats take their own holds joined to the same booking atomically - all confirm together or the addition fails cleanly.
06Sold out - do we need a waitlist?
Out of scope day one, but expired-hold releases are emitted as observable events so a future waitlist can subscribe without redesign.
Out of scopeDynamic pricing for hot events · Admin and event-coordinator tooling for creating events · Viewing past bookings, ticket transfer, and resale
01Where do we need strong consistency, and where can data be stale?
Consistency for booking — a seat never sells twice; availability for browse/search — the seat map may lag seconds behind reality.
02What does a flash on-sale look like at peak?
One hot event can draw ~10M users at on-sale — admission control (waiting room + token bucket) absorbs the spike before it ever reaches seat inventory.
03How fast should browsing and search feel?
Search under ~500 ms; seat-map views served cache/CDN-first. Read-heavy overall at roughly 100:1.
04How long can a hold last, and what happens on expiry?
Holds are short (5-10 minutes) with TTL auto-release — abandoned checkouts return seats without manual cleanup, and holds must outlive payment-provider latency.
05What happens when a confirm request or payment webhook arrives twice?
Confirm is idempotent per booking_id: retries and duplicate webhooks never double-charge or double-book.
Real interviews probe far more than a tidy list. These are the scope questions that separate candidates who interrogate the problem from those who recite it.
Treat every estimate as a pressure that justifies a component: cache, queue, partition, replica, worker pool, or fallback path.
On-sale contention
~10M users contending for ~50K seats at one on-sale moment10,000,000 ÷ 50,000 ≈ 200 users per seat
Almost everyone must be absorbed by the waiting room — admission control decides who even reaches booking.
Reserve write burst
First minute of on-sale: admitted users each attempt a holdadmit 50K users/min ≈ 800 reserve attempts/s against one event partition
Per-event partitioning + short atomic transitions keep the hot partition alive; other events stay unaffected.
Browse read skew
Read-heavy at ~100:1 — seat-map polling dominates800 writes/s × 100 ≈ 80K seat-map reads/s at peak
Serve views from cache/CDN with seconds of staleness — the inventory database never sees browse traffic.
Hold TTL vs payment latency
External payment confirm p95 is seconds; users fill forms for minutesTTL 5-10 min ≫ payment p95 ~3-10 s
Generous TTL avoids holds expiring mid-payment; expiry auto-releases abandoned seats without cleanup jobs.
Search latency budget
Search target < 500 ms end-to-endinverted-index query ~50-100 ms + ranking + network ≈ well under 500 ms
A full-text index (not LIKE scans) is required; cache repeated queries and CDN non-personalized results.
Decision example
Picture the on-sale: ~10M people want ~50K seats — about 200 people per seat. The fight is over each seat's state, so writes to a seat must happen one at a time, while everyone who is just browsing gets served from cache.
I would do three things. First, put everyone in a waiting room and let them into the booking flow at a controlled rate, so the seat database only ever sees traffic it can survive. Second, when a user picks seats, hold them for 5-10 minutes — pay inside that window or the seats go back on sale automatically. Third, make "check the seat is free AND mark it held" one single atomic step (a row lock, or an update that only succeeds if nobody changed the seat in between), so two buyers can never both grab it.
What I would NOT do: read "seat is free" first, then mark it held as a second step. In the gap between those two steps another buyer can do the same read — both think they won, and the seat sells twice. The check and the update must be one step, and the loser should get a clear "someone beat you to it" response (HTTP 409), not a silent failure.
If the venue is general admission — no specific seats, just a capacity number — per-seat locking is overkill. I would keep one atomic counter of remaining capacity and simply stop selling when it hits zero.
Draw the write path and the read path as separate lanes — they carry different traffic and justify different components.
Booking is the spine; browse and search never touch seat inventory (dashed = read side, off the booking hot path). An expired hold returns seats automatically.
Reserve takes a TTL hold; confirm charges payment idempotently and flips seats to booked in one atomic transition — check and update must be serialized (row lock or version CAS), because a check-then-act gap is a TOCTOU (time-of-check-to-time-of-use) race that double-sells.
Event pages are pre-rendered and CDN-cached so a flash sale never hits app servers for static content; availability may lag seconds — the booking transaction is where truth is enforced.
Before optimizing, make the contract inspectable: endpoints, entities, ownership, retries, and state.
GET/events/{event_id}
res200 { event, venue, seat_map, availability }
Cache/CDN-first; availability may lag seconds — booking is where truth is enforced.
GET/events/search?keyword&date&location
res200 Event[]
Inverted index (full-text) — sub-500 ms including fuzzy matches.
POST/bookings
req{ event_id, ticket_ids[] }
res201 { booking_id, hold_expires_at } · 409 seat already held or sold
Creates the TTL hold: seats flip to held atomically or the whole request fails — no partial holds.
POST/bookings/{booking_id}/confirm
req{ payment_token, idempotency_key }
res200 confirmed · 402 payment failed (hold keeps ticking) · 410 hold expired
Idempotent per booking_id: payment-provider retries and duplicate webhooks are safe.
Core entities
Eventevent_id (PK) · venue_id · performer · starts_at · on_sale_at
Ticketticket_id (PK) · event_id · section/row/seat · price · status: available/held/booked · version
status + version drive optimistic concurrency; partition by event_id so one on-sale cannot degrade other events.
Bookingbooking_id (PK) · user_id · ticket_ids · total · status: pending/confirmed/failed · idempotency_key
Useruser_id (PK) · email · created_at
Pick one lane for the final third of the interview. Each lane gives you the topic, the interviewer question it should answer, and the failure mode to avoid.
FocusSeat states
AskWalk a seat through available → held → sold. What exactly flips each state, and can two people ever hold the same seat?
AvoidHolds without a TTL — abandoned carts lock seats forever.
FocusReserve first, confirm later
AskWhy hold the seat before payment, and what happens to it if the payment never finishes?
AvoidMarking the seat sold at reserve time — a failed payment then makes it unsellable.
FocusStopping double-sell
AskRow lock, version check (CAS), or atomic counter — how does each stop two buyers winning the same seat, and what does each cost under contention?
AvoidPure optimistic retries in a flash sale — most buyers fail again and again instead of waiting fairly.
FocusSurviving the on-sale spike
Ask10M people hit one on-sale. How do you let them wait fairly instead of erroring most of them out?
AvoidLetting the whole herd reach seat inventory — the waiting room exists to protect it.
FocusPaying exactly once
AskThe confirm request arrives twice — a retry or a double click. How do you make sure the card is charged once and the seat sold once?
AvoidNo idempotency key on confirm — a network retry double-charges or double-sells.
Talk through Ticketmaster out loud and get AI scoring on the explanation.