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
DECRit (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.
