Skip to content

Online Ticketing / Ticket Rush — Architecture Template

Representative products / prototypes: Ticketmaster, SeatGeek, Damai, 12306, and all kinds of "flash sales" One-line definition: When a flood of users fight over a limited supply of seats / inventory the instant sales open, guarantee no overselling, relative fairness, and that the system isn't knocked over.


1. One-Line Definition

A ticket-rush system = the head-on battlefield where "extreme instantaneous concurrency" collides with "limited, scarce resources."

A million people fight over tens of thousands of tickets in the same second. It's the extreme version of an e-commerce flash sale, with one extra dimension: a ticket is often "a specific seat" (there's only one Row 3, Seat 12). Its entire design works to satisfy three nearly conflicting things at once: never oversell, be as fair as possible, and don't crash.

2. Business Essence: What Problem Does It Solve?

It sells an extremely limited resource (tickets / seats), in an extremely concentrated window of time (the instant sales open), to an extremely huge crowd.

What makes this special is "sale-open equals peak": no traffic normally, then traffic spikes thousands-fold the instant sales open, then settles back to calm a few minutes later. Architecting for this kind of spike is a completely different mindset from architecting for "steady growth."

Three iron rules, in priority order: no overselling (the bottom line) > no crashing (the prerequisite) > fairness (the experience). Selling a ticket that doesn't exist is an incident; if the system crashes, no one gets anything; if it's unfair, the reputation collapses.

3. Core Requirements & Constraints

Functional requirements:

  • [ ] Releasing tickets / inventory management (possibly down to the seat)
  • [ ] Grabbing tickets: decrement inventory / lock a seat
  • [ ] Seat locking (hold it while an order is placed but unpaid) + timeout release
  • [ ] Order placement, payment, ticket issuance
  • [ ] Queuing, purchase limits, anti-bot

Non-functional requirements / quality attributes:

Quality attributeTargetWhy it matters for this kind of system
No oversellingAbsoluteSelling a non-existent ticket is a major incident
Peak capacityWithstand the instant-sale-open floodLow normally, exploding the instant sales open — a classic spike
FairnessFirst-come-first-served / anti-botSwept clean by scalper scripts, reputation collapses
Real-time inventoryAccurate remaining-tickets / seat statusUsers want to see "how many are left"

Key constraints (boundaries you cannot cross):

  • 🔴 Inventory is limited and precise: each seat is unique and can't be sold twice.
  • 🔴 Concurrency is extreme and instantaneous: the write contention the instant sales open is concentrated on a tiny number of "hot inventory" rows.
  • 🔴 There's a "locking" intermediate state: a user has placed an order but not yet paid — the ticket can neither be sold to someone else nor held forever.
  • 🔪 Scalpers / scripts: professional gangs use machines to grab, so fairness faces real adversarial pressure.

4. Architecture Overview

   The instant sales open: a million users pour in
   ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼
┌──────────────────────────────────────────────┐
│  Virtual waiting room / queue                  │
│  (hold the flood [outside] the core system)    │
│  • Everyone enters the waiting room first,      │
│    gets a queue number                          │
│  • Admit in batches at [a rate the system can   │
│    bear] into the ticket rush                   │
│  • Anti-bot: verification, rate-limiting, risk  │
│    control filter once at this layer            │
└───────────────────────┬──────────────────────┘
                        ▼ Admission tokens (a trickle, not a flood)
┌──────────────────────────────────────────────┐
│  Ticket-rush / inventory service               │
│  • [Atomic] inventory decrement (hot inventory  │
│    in memory, never oversell)                   │
│  • Lock the seat (temporary hold)               │
└───────────────────────┬──────────────────────┘
                        ▼ Grabbed → create order (status = pending payment)
┌──────────────────────────────────────────────┐
│  Order state machine → payment → ticket issue   │
│  ⏰ Payment times out ──▶ auto-release the locked  │
│     ticket, return it to available              │
└──────────────────────────────────────────────┘

The soul is that top layer, the virtual waiting room: its job isn't "to make everyone queue," but to hold the flood outside the core system and "reshape" the traffic into a steady stream matched to the system's real capacity. Without it, the core system gets knocked flat in the very second sales open.

5. Component Responsibilities

  • Virtual waiting room / queue: when sales open, everyone enters the queue first and is admitted in batches per the system's capacity. Why it's needed: this is the foundation of withstanding the flood — protecting the core system from being killed by instantaneous traffic (see Decision 1).
  • Ticket-rush / inventory service: decrements inventory with an atomic operation, never overselling. Why it's needed: preventing overselling is the bottom line, and a plain "read-modify-write" will inevitably oversell under high concurrency (see Decision 2).
  • Seat locking: temporarily holds a seat when an order is placed, giving the user time to pay. Why it's needed: a seat has a "currently being bought by someone" intermediate state.
  • Timeout release: reclaims locks that are "held but unpaid." Why it's needed: otherwise tickets get held to death, neither sellable nor returnable (see Decision 3).
  • Order state machine: manages "pending payment → paid → issued / cancelled." Why it's needed: issuance concerns money and inventory, so state must not get out of order.
  • Anti-bot risk control: identifies bots / scalpers. Why it's needed: fairness faces professional adversaries.

6. Key Data Flows

Scenario 1: The ticket rush when sales open (from flood to issuance)

1. Sales open, a million people pour in ──▶ all enter the [virtual waiting room],
   get a queue number
2. The system admits in batches at a rate of "N per second it can handle" ──▶
   into the ticket-rush service
3. Rush: do an [atomic decrement] on the hot session's inventory
      Decrement succeeds ──▶ lock the seat, create order (pending payment, 10 min)
      Inventory is 0 ──▶ return "sold out"
4. User pays ──▶ issue the ticket, inventory officially sold
5. ⏰ Not paid in 10 minutes ──▶ auto-release, this ticket returns to the available pool

Scenario 2: Why no overselling (atomic decrement)

✗ Wrong: read the remaining count first (reads 1) → both requests think there's still
        one → both decrement → 2 tickets sold (oversold!)
✓ Right: use an [atomic operation] "decrement and return the result" — only one request
        can bring the last 1 down to 0, and the other atomic operation returns
        "insufficient" → only 1 ticket sold

7. Data Model & Storage Choices

Core entities: inventory / seat (status: available / locked / sold); order (state machine); queue token.

DataStorage typeWhy
Hot-session inventoryIn-memory KV (atomic operations)Write contention is extremely hot; DB row locks can't take the instantaneous flood
Seat map / statusIn-memory + relational for the ledgerHigh real-time demand, must ultimately persist
OrdersRelational (strongly consistent)Concern money and issuance, need transactions
Queue tokensIn-memory KVHigh-frequency, ephemeral

Teaching point: "hot inventory" is a super write hotspot — one blockbuster session's inventory is fought over by a million requests on the same row in an instant. Putting it in in-memory storage for atomic decrement, rather than making one DB row bear it, is the key to surviving the flood.

8. Key Architecture Decisions & Trade-offs ⭐

Decision 1: The virtual waiting room for peak-shaving (the foundation of withstanding the flood) ⭐

  • No peak-shaving, letting everyone hit the core system directly: the core system gets knocked flat the instant sales open, and nobody gets anything.
  • Virtual waiting room: hold people outside the door in a queue, admit them per the system's capacity.
  • Leaning: large ticket rushes must add a waiting room. Holding the flood outside the door is far more effective than frantically adding machines inside it — this is the first principle for handling spike traffic.

Decision 2: How do you guarantee inventory decrement doesn't oversell? ⭐

  • DB "read remaining - subtract remaining - write back": non-atomic, will inevitably oversell under high concurrency.
  • DB row lock / optimistic lock: can prevent overselling, but the hot row becomes a bottleneck under the flood.
  • In-memory atomic decrement (single-threaded atomic operation): fast and oversell-free.
  • Leaning: for modest concurrency use a DB row lock / optimistic lock; for hot, flooded sessions use in-memory atomic decrement, then persist asynchronously. See Section 12 for details.

Decision 3: The seat-locking intermediate state — what about "held but unpaid"? ⭐

  • No lock: the user picks a seat, hasn't paid, and it's grabbed by someone else → an experience disaster.
  • Locked with no timeout: held but unpaid, the ticket can never be sold.
  • Lock + auto-release on timeout.
  • Leaning: must do "lock + timeout release." This is the universal pattern for "temporarily holding a scarce resource" — same as distributed locks and inventory reservation.

Decision 4: Grab eligibility synchronously, run the flow asynchronously.

  • Make "grabbing eligibility (decrementing inventory)" synchronous, blazing fast, and atomic; make the subsequent "order placement, payment" an asynchronous flow.
  • Leaning: the better the core contention point — lighter and faster — the better; push the heavy lifting to after you've grabbed it and do it slowly.

9. Scaling & Bottlenecks

  • First bottleneck: the sale-open peak. → Fix: virtual waiting room peak-shaving (the fundamental means) + front-end staticization + CDN.
  • Second bottleneck: write contention on hot inventory. → Fix: hot inventory in memory with atomic decrement; when extremely hot, segment the inventory (split 1000 tickets into 10 segments of 100 each, spreading the contention).
  • Third bottleneck: read amplification from checking remaining tickets. → Fix: multi-level caching (cache the remaining-tickets status, tolerate a few seconds of lag).
  • Fourth bottleneck: the queue system itself must withstand everyone. → Fix: the waiting room itself must be made dead-simple and massively horizontally scalable.

10. Security & Compliance Essentials

  • 🔴 Anti-bot / anti-script ticket grabbing: CAPTCHA, device fingerprinting, risk control, real-name + purchase limits, to fight scalpers — this is the technical line of defense for fairness.
  • Overselling protection: atomic decrement is a security matter (overselling = selling a non-existent asset).
  • Anti-scraping interfaces: pre-sale probing and remaining-tickets-scraping interfaces must all be rate-limited.
  • Payment security: see the payment system template.

11. Common Pitfalls / Anti-patterns

  • Letting everyone hit the core system directly when sales open → ✅ virtual waiting room peak-shaving, hold the flood outside the door.
  • Using non-atomic "read remaining - subtract remaining" decrement → ✅ atomic operation / row lock, or it will inevitably oversell.
  • Locking a seat with no timeout → ✅ auto-release on timeout, don't let tickets get held to death.
  • Cramming hot inventory into a plain database to bear the writes → ✅ hot inventory in memory with atomic decrement, segment it when necessary.
  • No bot defense → ✅ risk control + real-name + purchase limits, hold the line on fairness.

12. Evolution Path: MVP → Growth → Maturity (how to set it up at each stage)

StageScaleHow to set it up (specifics)What to worry about now
MVPSmall event sign-upsA DB row lock / optimistic lock to decrement inventory is enough; concurrency is modest, no need for a heavyweight approachFirst guarantee no overselling, don't over-engineer
GrowthMedium ticket rushesHot inventory in in-memory atomic decrement, seat-lock timeout release, purchase limits, basic anti-scraping, async order placementHot-write contention, overselling, seat-hold release
MaturityDamai / 12306 scaleVirtual waiting room peak-shaving, segmented inventory, multi-level cache for remaining tickets, risk control vs scalpers, end-to-end asyncPeak capacity, fairness adversaries, stability

13. Reusable Takeaways

  • 💡 "Holding the flood outside the door" is more fundamental than "adding machines inside it." Queuing / waiting rooms / rate-limiting are the first choice for handling instantaneous spike traffic — this shares roots with message-queue peak-shaving.
  • 💡 Atomic operations are the lifeblood of preventing overselling: any scenario of "fighting over a limited resource" (flash sale, coupon rush, seat rush) must use atomic decrement, not "read-modify-write."
  • 💡 "Hold + timeout release" is the universal pattern for handling "temporarily holding a scarce resource": seat reservation, inventory reservation, distributed locks — all are it.
  • 💡 Put super-hot data in memory: making one database row bear a million concurrent writes is a doomed bottleneck; only in-memory atomic operations can take it.

🎯 Quick Quiz

🤔What is the most fundamental means of withstanding the instant-sale-open ticket-rush flood?
  • AFrantically add servers and brute-force it
  • BA virtual waiting room: hold the flood outside the core system and admit by capacity
  • CCap the total number of tickets sold

References & Further Reading

This template is compiled from the following public engineering materials. The core difficulties of ticket-rush / ticketing systems (virtual waiting room, peak-shaving, seat locking) are explained thoroughly in the pieces below.

📖 Engineering articles / solutions:


📌 Remember a ticket-rush system in one line: it isn't "a website that sells tickets" — it's "a battlefield where an extreme instantaneous flood fights over scarce resources." Every design decision answers one question: 'How do we simultaneously achieve no overselling, no crashing, and relative fairness?' — hold the flood outside the door, guard inventory with atomic operations, and put a timeout on seat holds.