How a platform sells exactly one hundred units to one hundred people out of a million who all pressed buy in the same second.
A flash sale is one of the most hostile workloads in software. Demand is not merely high, it is synchronised — a million people arrive in the same second, all wanting the same row in the same database table.
Ordinary scaling advice does not help. Adding servers multiplies the number of processes fighting over one counter. The bottleneck is not capacity, it is contention on a single shared number that must never go below zero.
And the business constraint is unforgiving. Selling one extra unit is not a rounding error, it is a cancelled order, a refund and an angry customer. Correctness cannot be traded for throughput.
Think of it like this: it is a stadium with one hundred seats and a million people sprinting at the door. The engineering is almost entirely about the doorway, not about the stadium.
Flash sales combine several individually difficult problems into one event:
Every request targets the same product record, so the load cannot be spread by sharding on product.
Two requests reading the same stock count simultaneously must not both succeed in claiming the last unit.
Load can rise by several orders of magnitude in seconds, far faster than autoscaling can react.
Reserved stock held by people who never pay must be released, or the item sells out without selling.
Automated buyers will take everything unless deliberately countered, and customers notice.
The design pushes as much work as possible away from the contended resource: static content is cached at the edge, arrivals are shaped by a queue, and only a thin, fast, atomic operation ever touches the stock counter.
Product pages, images and sale metadata are served entirely from CDN edges, so browsing traffic never reaches the origin.
In shortLooking at the product costs the system nothing, because it is all served from a copy nearby.
A virtual waiting room admits users into the purchase flow at a controlled rate rather than letting the whole crowd through at once.
In shortA doorman lets people in a few at a time instead of opening the doors to everyone.
The authoritative available count lives in a fast in-memory store supporting atomic decrement, not in the relational database.
In shortThe running total lives somewhere very fast that can count down safely.
Claims a unit atomically and issues a short-lived hold, so a buyer has a guaranteed unit for a few minutes while they pay.
In shortIt puts your item aside with a timer while you get your card out.
Successful reservations are written to a durable queue and processed asynchronously into real orders, decoupling checkout from order creation.
In shortOnce your item is held, the paperwork happens in the background.
The relational system of record persists confirmed orders and reconciles against the counter, but is never in the hot path.
In shortThe proper database records the sale afterwards, well out of the rush.
The product page is served from cache. No database is touched, no matter how many people are looking.
In shortMillions can stare at the page without the system breaking a sweat.
When the sale opens, users are placed in a queue and admitted at a rate the backend can actually sustain.
In shortYou get a place in line rather than a broken page.
On admission, a single atomic operation decrements the counter. If the result is negative, the claim fails immediately.
In shortOne quick, safe grab at the last units — you either get one or you do not.
A successful claim creates a time-limited reservation, giving the buyer a window to complete payment without competing further.
In shortYour unit is yours for a few minutes while you pay.
Payment confirmation converts the hold into an order. Failure or timeout releases the unit back to the pool.
In shortPay and it is yours; wander off and it goes back on sale.
Asynchronously, orders are written to the durable store and periodically reconciled against the counter to catch any drift.
In shortAfterwards the books are checked to make sure the numbers still agree.
Understanding precisely why the obvious implementation fails is the whole point. The bug is not a performance problem, it is a correctness one.
Two requests both read a stock of one, both conclude a unit is available, and both write zero. Two units are sold; one existed.
In shortTwo people check the shelf at the same instant, both see the last item, and both take it.
Locking the product row makes it correct but serialises every buyer behind one lock, collapsing throughput and exhausting the connection pool.
In shortMaking everyone queue for one shelf is safe but agonisingly slow, and the queue itself falls over.
Sharding by product cannot help when the entire event concerns one product — all traffic lands on one shard regardless.
In shortYou cannot spread the load out when everybody wants the exact same thing.
Failed requests are retried by clients, so a struggling system receives more traffic precisely when it can least handle it.
In shortWhen it slows down, everyone hits refresh, which makes it slower.
The natural implementation reads the stock, checks it, then writes the new value. Under contention this is not slow — it is wrong:
In short: the fix is to stop asking whether stock is available and then taking it. Instead, take it in one indivisible operation and look at what you got back. If the counter went negative, you did not get one — and you hand it straight back.
The most effective optimisation is preventing most of the traffic from reaching the contended path at all.
Users are given a queue position and admitted gradually, converting an instantaneous spike into a manageable stream.
In shortA digital queue turns a stampede into an orderly line.
Once reservations exceed available stock, further arrivals are told immediately that the item is gone, without touching the counter.
In shortOnce it is sold out, everyone else is told instantly rather than being allowed to try.
Eligible buyers can be issued tokens before the sale begins, moving authentication and eligibility checks out of the critical window.
In shortThe checks happen beforehand, so the moment of sale is as thin as possible.
Rate limiting per account and device, plus challenges on suspicious patterns, keep automated buyers from consuming the entire allocation.
In shortScripts are slowed down so real people get a chance.
Surviving the event depends far more on keeping load away from the contended resource than on making that resource faster:
| Layer | Common Choices |
|---|---|
| Edge Delivery | CDN with aggressive caching for product and sale pages |
| Admission Control | Queueing service or waiting-room layer at the edge |
| Counter Store | Redis with atomic DECR, or Lua scripts for compound conditions |
| Reservation | Short-TTL keys with automatic expiry for abandoned holds |
| Messaging | Kafka or SQS for durable, asynchronous order processing |
| System of Record | Relational database, written outside the hot path |
| Protection | Rate limiting, bot detection and circuit breakers |
A flash sale strips system design down to its essentials: one shared resource, extreme concurrency and zero tolerance for error. The techniques — atomic operations, reservation with expiry, admission control and idempotency — apply to any system where limited inventory meets simultaneous demand, from ticketing to appointment booking.
A quick, no-nonsense translation of the technical terms used above.
When the result depends on the precise timing of two operations, and some orderings produce a wrong answer.
An action that completes entirely or not at all, with no possibility of another operation observing it half-done.
Allowing concurrent work and detecting conflicts at write time, rather than locking up front.
A temporary claim on stock that guarantees availability for a limited period.
A unique token attached to a request so that repeating it has the same effect as sending it once.
A queue that admits users into a system at a controlled rate during a demand spike.
Deliberately rejecting some requests to keep the system healthy for the rest.
A single shard receiving disproportionate traffic, defeating the purpose of sharding.