System Design Guides

Design a Ticketing Platform

A high-signal system design guide for Ticketmaster-style ticket sales with inventory holds, queues, payment, seat maps, and flash-sale traffic.

inventoryqueuespaymentsflash salesconsistency

Interview Prompt

Design a platform where users can browse events, select seats, reserve tickets, and complete purchase during high-demand sales.

Identifies ticket inventory as the consistency-critical part of the system.

Uses temporary holds with expiration instead of charging immediately.

Protects the system with waiting rooms, rate limits, and bot controls.

Handles payment authorization, order confirmation, and hold release.

Step 1

Clarify functional and non-functional requirements first.

Functional Requirements

  • Users can browse events, venues, sections, and available seats.
  • Users can select seats and place a short-lived hold.
  • Users can complete payment before the hold expires.
  • The system issues tickets and sends confirmation.
  • The platform supports high-demand onsales with waiting rooms.

Non-Functional Requirements

  • Never sell the same seat twice.
  • Seat availability should be reasonably fresh during normal browsing.
  • Checkout should remain consistent even under extreme load.
  • The system should defend against bots and abusive purchase patterns.
  • Payment failures should release inventory reliably.

Scale Assumptions

  • A major event has 80,000 seats.
  • 1 million users may enter the waiting room for a popular onsale.
  • Seat map browsing may be 100 times larger than completed purchases.
  • A hold lasts 5 to 10 minutes.

Inventory writes

Bounded by seats

The number of successful holds cannot exceed event inventory, but attempts can be enormous.

Waiting room

Millions of users

Queue service must absorb traffic before users reach seat selection.

Seat reads

Very high burst

Seat maps and availability snapshots are the main read load.

Hold expiration

Continuous background work

Expired holds must return seats to available inventory without manual cleanup.

Step 2

Identify the key entities before picking storage.

EntityFields and RelationshipsInterview Notes
Eventevent_id, venue_id, name, start_time, sale_stateSale state controls browsing, waiting room, and checkout behavior.
SeatInventoryevent_id, seat_id, status, hold_id, versionThe consistency-critical row. Use conditional updates or transactions.
Holdhold_id, user_id, seat_ids, expires_at, statusExpires automatically and releases seats if not converted.
Orderorder_id, user_id, hold_id, payment_id, statusTracks payment and ticket issuance lifecycle.

Step 3

Define the APIs around the user flows.

InterfaceRequest / ResponseContract Notes
GET /v1/events/{eventId}/availabilityReturns section availability or seat-level snapshotServe cached snapshots and refresh frequently during onsales.
POST /v1/holds{ eventId, seatIds, idempotencyKey } -> { holdId, expiresAt }Atomic inventory transition from available to held.
POST /v1/orders{ holdId, paymentMethodId } -> { orderId, status }Authorize payment, capture if required, then confirm tickets.
POST /v1/waiting-room/join{ eventId } -> { positionToken }Controls admission into inventory-sensitive endpoints.

Step 4

Trace the critical data flow step by step.

01

Waiting room

Users first enter a queue that meters traffic into seat selection and reduces bot-driven request spikes.

02

Availability read

Clients browse cached section or seat snapshots. Exact truth is checked only during hold creation.

03

Hold seats

Inventory service atomically changes selected seats from available to held with a hold expiration timestamp.

04

Checkout

Order service validates hold ownership and expiry, authorizes payment, confirms inventory, and issues tickets.

05

Expiration and recovery

Background workers release expired holds and reconcile payments, orders, and inventory transitions.

Step 5

Convert the flow into a high-level design.

Final Design

Ticketing Platform final architecture

Loading Diagram

Serving Layer

Start with clients, routing, APIs, and the main synchronous path users depend on for this problem.

State Layer

Anchor the design around the key entities: Event, SeatInventory, Hold, Order.

Async Layer

Move slow, high-volume, or failure-prone work behind queues, workers, streams, caches, or background reconciliation.

Step 6

Deep dives interviewers are likely to probe.

Inventory correctness

  • Use conditional updates on seat status and version to prevent double sell.
  • Seat selection can show stale data, but hold creation must be strongly consistent.
  • Holds should expire even if checkout workers fail.

Waiting room design

  • Queue tokens should be signed and short lived.
  • Admission rate should adapt to checkout capacity and payment provider health.
  • Users should not refresh their way to a better position.

Payments

  • Use idempotency keys for payment attempts.
  • Do not confirm tickets until payment authorization or capture succeeds.
  • Reconciliation jobs should detect paid orders without issued tickets and held seats without orders.

Step 7

Tradeoffs to explain out loud.

Cached availability vs exact availability

Use When

Cache browse views to handle high read volume.

Watch Out

Users may see seats that fail during hold creation.

Seat-level inventory vs section-level inventory

Use When

Seat-level is required for assigned seating.

Watch Out

General admission can use simpler counters but still needs atomic decrement.

Long holds vs short holds

Use When

Short holds increase inventory turnover and reduce abandoned carts.

Watch Out

Too-short holds frustrate users during payment or account friction.

Avoid

Common mistakes that weaken the answer.

  • Using cache availability as the source of truth for purchase.
  • Not expiring holds reliably.
  • Charging payment before inventory is reserved.
  • Ignoring bot traffic and waiting room admission.
  • Allowing checkout retries to create duplicate orders.

Step 8

Follow-up questions with strong answers.

How do you guarantee a seat is not sold twice?

Make inventory transition atomic with conditional update or transaction on seat status/version, and only issue tickets after the held seat is confirmed for one order.

What if payment succeeds but ticket issuance fails?

Keep order in a pending-confirmation state, retry issuance idempotently, and run reconciliation before releasing inventory or refunding.

How do you handle bots?

Use waiting room tokens, rate limits, device and account reputation, CAPTCHA for suspicious flows, purchase limits, and fraud review.

Step 9

What a strong answer should signal.

Consistency

Clearly identifies atomic inventory hold as the critical guarantee.

Traffic control

Uses waiting rooms and cached availability to survive flash-sale load.

Payments

Handles idempotency, authorization, capture, confirmation, and reconciliation.

Edge cases

Covers hold expiry, stale maps, bots, cancellations, and partial failures.

Practice this problem under interview conditions.

Read the guide, then run the prompt live with LeetSys so you can practice requirements, key entities, API design, data flow, whiteboarding, tradeoff narration, and follow-up handling.

Practice Now

Related Guides