Question Breakdowns

Flash Sale

A worked system design: sell a tiny, fixed stock of a hot item to a massive, simultaneous crowd without overselling or falling over. Extreme contention, the spike, and protecting the inventory decrement.


A flash sale puts a small, fixed quantity of a hot item on sale at an exact moment, and a massive crowd — far larger than the stock — all try to buy it in the same instant. It's the most extreme contention problem in this track: a thundering herd of millions competing for maybe 1,000 units, where you must never oversell and must not fall over under a traffic spike orders of magnitude above normal. It combines Ticket Booking's scarce-inventory correctness with brutal scale.

1. Requirements

Functional:

  • At sale start, users attempt to buy a limited-stock item.
  • Exactly the available quantity is sold — no more, no less.
  • Winners proceed to checkout; the rest are cleanly told it's sold out.

Non-functional:

  • No overselling, ever — 1,000 units means at most 1,000 sold. Absolute.
  • Survive the spike — millions of simultaneous requests at t=0; the system must degrade gracefully, not crash.
  • Fast rejection — the vast majority will fail; failing them cheaply is as important as serving winners.
  • Fair-ish — a reasonable ordering (first-come, or random admission).

2. The shape of the problem

Two things are true at once: almost everyone will lose (millions chasing thousands of units), and the inventory decrement is a single hot contended counter. So the strategy is: shed the losing traffic as early and cheaply as possible, and protect the one critical operation — decrementing stock — with something fast and atomic. Don't let millions of doomed requests reach your database.

3. Layered defense: shed load early

Filter the crowd down in stages, each cheaper and earlier than the last:

CDN / static page ─► waiting room / queue ─► admit a trickle ─► stock decrement (hot path)
  (most traffic)       (holds the herd)       (only ~enough)      (tiny, protected)
  • Serve the sale page statically from a CDN — no app servers touched for browsing.
  • Virtual waiting room / queue: admit users into the actual purchase flow in a controlled trickle rather than letting the whole herd hit the backend at once. This is the single most important technique — it converts an instantaneous spike into manageable, steady load. Users wait in line; the backend only ever sees as much traffic as it can handle.
  • Early rejection: once stock is provably gone, reject remaining users immediately at the edge ("sold out") without touching the core — most requests end here, cheaply.

4. Protecting the inventory decrement

The heart is one hot counter: "how many left?" It must be decremented atomically so you can't sell unit #1,001:

  • Atomic decrement in Redis: hold the stock count in Redis and DECR it (or a small Lua script) — an in-memory atomic op handles enormous throughput and guarantees you never go below zero (reject when the decrement would). Redis, not the database, absorbs the contention.
  • Reserve, then checkout: a successful decrement grants a short-lived reservation (with a TTL, like Ticket Booking); the user then checks out at leisure. If they abandon, the TTL returns the unit to stock.
  • Pre-load stock into Redis before the sale; reconcile to the durable database asynchronously. The database is the system of record but is kept off the hot path.
admitted user → Redis DECR stock
   result >= 0 → reservation granted → proceed to checkout
   result <  0 → sold out (reject)

5. Decouple the slow parts

Winning the unit (the fast atomic decrement) is separate from order creation and payment (slow, DB-touching). Once a user holds a reservation, push the actual order creation through a queue to be processed steadily — so the spike is fully absorbed by the time real database work happens. Payment is its own payment flow with idempotency.

6. Deep dives

  • Hot-key limit: a single Redis counter has a throughput ceiling; if needed, split the stock into N shards (e.g. 10 counters of 100), route users across them, and a request only fails over to another shard when its own is empty — spreading the contention while keeping the total exact.
  • Bots/fairness: flash sales attract bots — rate-limit, require auth, and cap per-user purchases; admission can randomize to be fairer than pure first-come.
  • Graceful failure: every rejected user must get a fast, clear "sold out" — overload must degrade to clean rejections, never timeouts or crashes.
  • Idempotency: a user retrying must not consume two units — tie the decrement to a per-user key.

What to emphasise

Lead with shedding load early and protecting the atomic decrement:

"Two facts drive it: almost everyone loses, and stock is one hot contended counter. So I shed losing traffic as early and cheaply as possible — a static CDN sale page, then a virtual waiting room that admits users in a controlled trickle, converting the instantaneous spike into steady load the backend can handle, and I reject 'sold out' at the edge once stock is gone. The critical operation is the inventory decrement, which I do as an atomic DECR in Redis so it can't go below zero and never oversells — Redis, not the database, absorbs the contention, with stock pre-loaded and reconciled to the DB asynchronously. A successful decrement grants a TTL'd reservation, and order creation and payment are pushed onto a queue so the slow database work happens steadily after the spike. If one counter is a bottleneck I shard the stock across several while keeping the total exact."


That completes the Question Breakdowns. Each applies the same method — requirements, a scale check, the one decisive trade-off, then deep dives — to a different problem. Head back to Core Concepts to revisit the fundamentals, or to Patterns for the reusable building blocks these designs lean on.