How to stop overselling across multiple Shopify stores
Overselling between stores is a timing problem, not a stock problem. Here is the mechanism that causes it, why buffer stock is an expensive patch, and what actually closes the window.
Overselling across stores is almost never a stock-counting problem. The counts are right. The problem is when they are right, and in which store. This guide is about the window between those two things, because closing it is the whole job.
The mechanism
You have one shelf and two storefronts. There are three units on the shelf, and both stores say “3 in stock”.
Read “two storefronts” loosely. The same race happens inside a single store whenever one item is listed as several products carrying the same SKU — a bundle and its component, a seasonal relist, the same mug under two names. Shopify treats those as separate stocks, so selling one does not lower the others, and every word below applies unchanged. That version catches people out more often, because nothing about the setup looks like a sync problem at all.
- 10:00:00 — a customer buys all three in store A. Store A now says 0. The shelf is empty.
- 10:00:01 to 10:14:59 — store B still says 3. It has not been told anything.
- 10:07:12 — a customer in store B buys two units that do not exist.
- 10:15:00 — the sync runs and sets store B to 0. Fifteen minutes too late for that customer.
Nothing malfunctioned. The app did exactly what it promised. The window between step 1 and step 4 is the product’s design, and every scheduled sync has one — the interval is the window.
This is why "syncs every 15 minutes" and "prevents overselling" cannot both be true on a fast-moving SKU. The first sentence is a description of the risk, not a mitigation of it.
Why the window is worse than the interval suggests
Two things make the real exposure larger than the number in the pricing table.
Your risk is concentrated in exactly the wrong moments. The window only hurts when something sells during it, so your exposure scales with sales rate. A 15-minute window is harmless at 3am on a Tuesday and expensive during a launch or a sale — which is when you are least able to deal with the fallout.
The last unit is the one that matters. Sync lag on an item with 400 units in stock is invisible. Sync lag on an item with 2 left is an oversell. And low-stock items are disproportionately the ones customers are actively racing each other for.
The patch everyone tries first: buffer stock
Hold back a few units per SKU in each store. Publish 8 when you have 10. Now a customer has to clear the buffer inside the window before anyone oversells, which is much less likely.
It works, and it is a reasonable stopgap. It is also expensive in a way that is easy to under-count:
- The buffer is unsellable stock, multiplied across every SKU and every store.
- It has to be sized for your worst minutes, not your average ones, so it is oversized nearly all the time.
- It converts an occasional oversell into a permanent margin cost, and permanent costs stop being noticed.
- On low-stock items it silently hides the last units. An item with 2 left and a buffer of 2 shows as sold out and never sells.
Buffer stock is worth using while you fix the timing. It is not a fix for the timing.
What actually closes the window
1. Event-driven, not scheduled
The sync should start when the quantity changes, not when a timer fires. Shopify emits an inventory-level webhook the moment stock moves; a sync driven by that has a window measured in seconds, and — more importantly — a window that does not grow when you get busy. Polling gets worse under load, because more sales land per interval. Event-driven gets busier, not later.
2. Atomic writes, not read-then-write
This is the part that is usually invisible from the outside, and it matters more than raw speed.
The naive way to sync is: read the quantity from the store that owns it, then write that number into the other one. Between the read and the write — even two seconds — a sale can land in the store being written to. The write then blindly overwrites it, restoring a number that was already wrong, and now that store is over-stated by the sync itself.
The fix is a conditional write: “set this to 7, but only if it is still 9, which is what I based this on.” If the value moved, the write is rejected and retried against the new reality. Shopify’s inventory API supports this, and it is the difference between a sync that converges and one that fights the store it is writing to.
Worth asking any vendor directly: does your write use compare-and-set? A sync without it can produce oversells on its own, independent of how fast it runs.
3. One source of truth
If two stores can both write the authoritative quantity, you have a conflict problem, and every conflict resolution rule is wrong in some scenario. One-way sync — one store in charge, everything else follows — removes the question instead of answering it. Everyone edits stock in one admin. The rest mirror it.
This is a real constraint and worth naming: it means stock adjustments made in the stores that follow get overwritten. That is the point, and it is only the right trade when the stores are genuinely sharing one pool of physical stock.
How to tell if it is already happening
In rising order of how much it has already cost you:
- A difference check. Compare the same SKU’s quantity in both stores right now. Any gap is a window that is currently open. This is the only signal that finds the problem before a customer does — run it regularly, not once.
- Negative inventory. If any store shows a negative quantity, you have already sold something that was not there. This is proof, not a warning. One exception is worth knowing: a count that is negative and lower than every product sharing its SKU is not an oversell at all, because no run of real sales produces that — it is a second app’s writes being counted as sales.
- Cancellations shortly after purchase. Look at the rate of orders refunded or cancelled within a day, by SKU. A cluster on fast-moving items is what overselling looks like from the customer’s side.
- Support tickets containing “still hasn’t shipped”. The most expensive detector, because by then it has cost you the order and the relationship.
When it happens anyway
No amount of engineering makes the window exactly zero — a sale can always land in the same instant as another. What changes is how often, and what you do about it:
- Contact the customer before they contact you. An email the same day reads as competence; a week of silence reads as a scam.
- Offer a real choice — wait for restock, substitute, or refund now. Do not pick for them.
- Fix the count in the main store, not the one that follows, or the sync will undo you.
- Check whether the SKU has a matching problem rather than a timing one. A duplicate SKU produces oversells that look like races but repeat forever.
Where StockUnison sits
StockUnison is built around the two mechanisms above: it syncs on Shopify’s inventory webhook rather than a schedule, and each write into a connected store is a single compare-and-set — it either applies to the quantity it was calculated from, or it is rejected and retried. Sync is one-way by design, so there is exactly one store that owns the number. A difference report compares every matched SKU across stores so you can see open gaps rather than infer them, and every write is in a log with its result.
It is free to run up to the point of writing, so the difference report can be used to find open gaps before committing to anything.
What it does not do: it cannot make the window zero, it will not stop an oversell caused by a duplicate SKU that was never matchable in the first place, and it does not manage buffer stock for you.
Common questions
Why do I oversell when my stores are synced?
Because 'synced' usually means 'synced on a schedule'. If an app polls every 15 minutes, then for up to 15 minutes after a sale in store A, store B is still advertising stock that no longer exists. Anyone who buys in that window is buying an item you cannot ship. The sync is working exactly as designed — the design has a window in it.
Does buffer stock fix overselling?
It hides it. Holding back a few units per SKU means the window has to be unusually busy before a customer reaches zero, so oversells become rarer without becoming impossible. The cost is that the buffer is unsellable inventory across every SKU and every store, and it has to grow as you get busier — which is precisely when the cash is worth most.
How fast does inventory sync need to be to prevent overselling?
Fast matters, but atomicity matters more. A sync that runs in two seconds and does read-then-write can still lose a race against a simultaneous sale. A sync that uses compare-and-set writes cannot: the write either applies to the quantity it was based on, or it is rejected and retried. Aim for event-driven rather than scheduled, and check that writes are conditional rather than blind.
How do I tell if I am already overselling?
Three signals. Negative inventory in any store is proof. A rising rate of cancelled or refunded orders shortly after purchase is the customer-facing symptom. And a difference check — comparing the same SKU's quantity across both stores — will show you the gap directly, which is the only one of the three that finds the problem before a customer does.
One item. One number.
StockUnison keeps one count wherever an item sells — across your Shopify stores, or across duplicate products in one. Matched by SKU, previewed before anything moves, and logged write by write.
Install on ShopifyFree plan you can stay on · live syncing from $19/mo