Overselling looks like a small problem. A customer orders something you don’t have, you apologize, you refund, you move on. Once a week, maybe. Annoying, not fatal.

It isn’t a small problem, and the reason is that the part you can see is the smallest part of it.

What one oversell actually costs

Start with the direct costs of a single incident:

  • Somebody finds it — usually a picker, usually after the order has been paid for.
  • Somebody calls or emails the customer. Ten minutes, plus the part nobody enjoys.
  • You refund, substitute, or back-order. Each of those costs something to handle.
  • If part of the order already shipped, you’re now paying for a split shipment.

Call it thirty to sixty minutes of attention and somewhere between $30 and $100, before you count anything you can’t put a number on.

Now the parts that never appear on an invoice:

Marketplace penalties. If you sell anywhere besides your own site, your cancellation rate is scored. Enough cancellations and you lose your buy-box position, your search placement, or the account. This is the cost that turns an annoyance into a serious problem, and it builds up quietly until you cross a line.

Trust, in the wrong places. The customer who gets the cancellation is more likely than average to be a new customer, because your regulars buy the things you always have. So the cost lands hardest on exactly the relationships you spent marketing money to create.

The cushion. This is the big one, and almost nobody counts it. After enough oversells, somebody decides to hold stock back — list 90% of what you have and keep a buffer. That buffer is now inventory you can never sell. On a $1M stock position, a 10% cushion is $100,000 of working capital sitting there doing nothing, forever, to make up for a number you don’t trust.

That’s the real price of overselling. Not the cancellations, but the money you tie up avoiding them.

Why the number is wrong to begin with

Almost always, one of four things:

  1. Stock is counted in one system and sold in another, and the thing keeping them in step is a person, or a nightly job, or both.
  2. Reserved stock is invisible. Units set aside for an open order, a pick in progress or a wholesale hold are still being counted as available.
  3. Reservations are per store, not shared. Something reserved by store A is still shown as available by store B. If you run more than one sales channel out of one warehouse, this alone will oversell you steadily.
  4. Incoming stock is treated as if it’s here. A confirmed purchase order is real, but it isn’t on the shelf, and mixing the two makes you look better stocked than you are.

The formula that ends it

The fix is to stop publishing “whatever the warehouse system says” and start publishing a number you work out. In the systems we build, sellable stock is one line, worked out per product, on a schedule:

sellable = max(0, on hand + confirmed orders in - work in progress - already promised)

Four parts, and each one has to earn its place:

  • on hand — physically in the building, according to one system. One system. If two systems disagree about what’s on hand, that’s a separate problem you have to fix first.
  • confirmed orders in — stock on a confirmed purchase order. Only include this if you’re willing to sell against it, and only if your confirmations are honest. Plenty of people set this to zero, and that’s a perfectly good answer.
  • work in progress — units on picks, transfers or jobs in flight. Physically there, not available.
  • already promised — units set aside for open orders. This is the one that has to be added up across every sales channel, not per store. Something reserved anywhere is reserved everywhere.

The max(0, ...) matters more than it looks. Without it, one bad count produces a negative number, and a negative number pushed into a store does anything from hiding the listing to deleting it. Stop at zero and let the sorting-out happen in the warehouse, not on your product page.

The second half of the fix is what happens when the number hits zero: the listing gets hidden automatically, and comes back automatically when stock returns. Doing it by hand drifts within a week, every time.

Getting it right in practice

Even a correct formula causes trouble if it’s pushed carelessly. Three rules that matter:

Send the number, not the change. Setting a product to 12 units has to be safe to do twice. If your sync sends “add 3” instead of “make it 12”, a retry will corrupt the count.

Plan for API limits. Store platforms limit how often you can call them. A sync that ignores that gets throttled exactly when you have the most to update — on a busy day. Budget the calls, back off when you’re told to, and update the things that changed first.

Write everything down. When a merchandiser asks why a product went out of stock at 3pm, “here’s the record: 40 on hand, 40 promised, 0 sellable, pushed at 15:02” ends the conversation in ten seconds. Without it, you’re re-arguing whether the system can be trusted every week.

What good looks like

You stop hearing about oversells. Then, a few weeks later, somebody asks whether you still need the cushion — and the answer is no, because the number on the site is now the real number.

That’s where the money actually is.

All posts