Skip to the lesson
Little Builders system design, explained small

Flash Sale Inventory Management

At exactly 10:00, a toy shop puts 100 golden toys on sale, and a million kids click the buy button in the same second. That is ten thousand kids for every toy. Two things can go wrong. The shop's computers can drown in the crowd and stop answering anyone at all. Or, in the scramble, the shop can sell 103 toys when it only has 100, and three kids get a sorry after being promised a toy. A good flash sale design keeps most of the crowd away from the delicate parts, lets people in at a safe speed, gets everything ready before the doors open, and makes taking a toy off the shelf a single step that two hands can never do at the same time.

The traffic spike

A million kids at one tiny shop door

On a normal day our toy shop gets a few hundred visitors a second. At 10:00 on sale day, it gets a million clicks in a few seconds. That is like a whole city trying to squeeze through one classroom door.

The danger is not only being slow. When too many requests arrive, every part of the system starts waiting on every other part. The database can only keep a limited number of conversations open at once (called connections). Requests pile up and time out, people click again, and the pile grows even bigger. The whole shop can fall over, even for someone just buying socks.

This crowd has an unusual shape, too. Most busy systems spread work across many different things. Here, a million requests all aim at one single number: how many golden toys are left. That one number becomes a hot spot, like one candy bowl with the whole school around it.

And we cannot simply add computers once the rush starts. Adding computers automatically (autoscaling) takes minutes, but this rush peaks in seconds. So everything has to be ready before 10:00.

Remember

A flash sale is a huge spike aimed at one tiny thing, so the plan must be ready before it starts.

Static pages, waiting rooms and rate shedding

Keep the crowd in a calm line outside, not crushed at the counter

Most of the crowd only wants to look at the toy page. That page is the same for everyone, so we make it static, like a printed poster, and hand it out from a CDN (content delivery network): a set of helper computers spread around the world that keep copies close to people. Handing out posters never bothers the shop itself. The number of toys left on the poster may be a few seconds old, and that is fine, because the real check happens later.

Next comes a virtual waiting room, like the rope line at a theme park ride. Everyone who presses buy joins the line, and the line lets people through only as fast as the shop can truly serve them, for example 2,000 a second. Some shops shuffle everyone who arrived before 10:00 into a random order, so being a few milliseconds faster does not matter. People in line see a calm waiting page instead of an error.

Rate shedding means politely turning away work you cannot serve, early, right at the front door. If the line is already far longer than the toys could ever cover, the people at the back can be told straight away that the toys will very likely be gone. Once every toy is reserved, the door switches to a friendly sold out page, so nobody waits for nothing. Saying no early is kinder and cheaper than letting people pile up, wait a minute, and then fail.

We also stop unfair grabbing: one golden toy per account, and checks that block bots, which are computer programs that click much faster than any person. The trade-off is that some real shoppers wait or are turned away, and the waiting room becomes one more piece that must work perfectly on the big day.

A theme-park rope line. The gate lets people in at one steady pace; the rest wait, or turn back. Hover to slow time and follow one.

Remember

Hand out the page from copies, let buyers in at a safe speed, and turn away what you cannot serve as early as possible.

Overselling and atomic reservation

Two kids grab the last cookie at the same moment

Imagine one cookie left in the jar. Ann looks in and sees 1. At the same moment, Ben looks in and also sees 1. Ann takes it and writes down 0 left. Ben takes it too and writes down 0 left. Both walk away happy, but there was only one cookie. That is overselling. The mix-up is called a race condition, because the result depends on who gets there first in a race nobody is refereeing.

In computers, this happens when the code reads the stock count in one step and writes the new count in a separate step. Between the read and the write, another request can sneak in and read the same old number. With a million requests in a few seconds, this is not a rare accident. It is almost certain.

The fix is to make check and take one single step that cannot be split in half. This is called an atomic operation, from an old word meaning cannot be cut. The counter handles one take at a time: if at least one toy is left, take it and say yes, all in one go. Otherwise say no. Ann gets yes, Ben gets sold out, and the count can never drop below zero.

Real tools give us this single step. A fast in-memory store such as Redis runs commands one at a time, so a tiny script that checks the count and subtracts one runs without anyone sneaking in between. A database can do it too, with one command that says: subtract one from the stock, but only if the stock is above zero, and tell me whether it worked. The thing to avoid is ever reading the number in one step and writing it back in another.

One cookie, two hands. Pick who reaches first. Checking and taking is one step, so that hand gets it and the other finds the plate bare.

Remember

Never read the stock and then write it in two steps. Check and take in one step.

Pre-allocation

Pour the candy into ten small bowls before the party

Even with a safe one-step counter, a single counter is still a hot spot. It can only handle one take at a time, so a million requests queue up behind it, like the whole school crowding one candy bowl. So before the sale we prepare. We copy the stock count from the main database into fast memory, and we split it: 100 toys become 10 buckets of 10. Each request goes to one bucket, so the crowd spreads over 10 small bowls instead of crushing one big one. Every bucket still uses the one-step check and take, so each bucket is safe on its own.

There is a catch. Bucket 3 might run empty while bucket 7 still has toys. Telling a kid sold out just because their bucket was empty would be wrong. So a request that lands on an empty bucket tries another one, and near the end the last few toys can be moved between buckets (rebalanced). The shop only says sold out when every bucket is empty. This adds some extra work and complexity in exchange for spreading the load.

Pre-allocation also means getting everything else ready early: starting extra servers well before 10:00 (pre-scaling), and loading the toy page and other common answers into caches, the quick-grab memory spots, ahead of time (pre-warming), so nothing starts cold just as the crowd arrives.

The candy is split into ten small bowls so the crowd spreads out. Take from one; if it is empty, you are sent on to the next.

Remember

Load the stock into fast memory before the sale, and split it so the crowd spreads out.

Reservations with a timer

Your name on the toy for ten minutes while you fetch your wallet

Getting a yes from the counter does not mean you have paid. It means the toy is held for you, like a librarian putting your name on the last copy of a book for ten minutes while you find your library card.

The hold has a timer. If you pay in time, the order is kept. If the timer runs out, a helper called the expiry worker notices the old hold, cancels it, and puts the toy back into a bucket so another shopper can get it. Without timers, people who wander off would lock up toys forever.

Kids double click, and phones lose signal and send the same thing again. So each buy request carries an idempotency key, a unique ticket number for that one purchase attempt. If the same ticket number arrives twice, the shop replies with the answer it already gave, instead of holding a second toy.

Two edges need clear rules. A payment can arrive just after the timer ran out, so the shop either holds a toy again if one is left, or refunds the money. And the timer length is a trade-off: too long and toys sit unsold while held, too short and slower payers lose their toy.

A toy saved for you on the hold shelf, with an hourglass. Slide through the minutes: when the sand runs out, the toy goes back on the shelf.

Remember

A yes is a hold with a timer. Unpaid holds expire and the toy goes back on the shelf.

Queues, durable orders and reconciliation

Write it in the big book later, but never lose the note

The fast memory counters are quick, but memory can lose its last few changes if a computer crashes. The main database, which saves things carefully on disk, is the source of truth: when the two disagree, the database wins. But it is far too slow to take a million writes in one second.

So after a successful hold, the shop drops a note into a queue, a line of messages that are kept safely even if a computer restarts. A worker takes notes from the queue at a steady pace and writes the orders into the database. The database does its own final check as well, subtracting stock only if some is left, so even if the fast counter hiccups, the true count never goes below zero.

After the sale we reconcile, which means comparing the books. Toys sold, plus toys still held, plus toys left must add up to 100. If the fast counters and the database disagree, the database wins and the rest is fixed. Very rarely, a shopper who got a yes from the fast counter may need an apology and a refund. Good shops design to keep that close to zero, and they plan what to say if it happens.

Order slips wait in a queue by the big book, the final word. Pick a slip: it is safe in line until it is written in the book.

Remember

Fast counters for speed, a queue for safety, and the database as the final word.

Quick recap

  1. A flash sale is a giant spike aimed at one tiny number: how many are left.
  2. Serve the product page from a CDN, let buyers in through a waiting room, and shed extra requests early with a polite answer.
  3. Overselling comes from reading and then writing in two steps. Always check and take in one atomic step.
  4. Pre-allocate: load stock into fast memory and split it into buckets so requests spread out. Pre-scale and pre-warm before the sale.
  5. A successful reservation is a hold with a timer. Unpaid holds expire and the stock goes back.
  6. Idempotency keys stop double clicks from holding two toys.
  7. Orders flow through a durable queue into the database, which is the source of truth and is reconciled after the sale.

Grown-up words

and what they mean in plain words

Flash sale
A sale with very little stock and a huge crowd arriving at once.
Overselling
Promising more items than you actually have.
Race condition
A bug where the result depends on which of two things happens first.
Atomic operation
A step that happens completely or not at all, with nobody sneaking in halfway.
Virtual waiting room
An online line that lets buyers in at a safe speed.
Rate shedding
Turning away extra requests early, so the rest can be served well.
Pre-allocation
Preparing stock in fast memory, split into buckets, before the sale starts.
Reservation hold
A short, timed promise that an item is saved for one shopper.
Idempotency key
A unique ticket number, so sending the same request twice has no extra effect.
Reconciliation
Comparing records afterwards and fixing any differences.