Guides

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: two products in one store carrying the same SKU produce this identically, and catch people out more often because nothing about the setup looks like a sync problem.)

  1. 10:00:00 — a customer buys all three in store A. Store A now says 0. The shelf is empty.
  2. 10:00:01 to 10:14:59 — store B still says 3. It has not been told anything.
  3. 10:07:12 — a customer in store B buys two units that do not exist.
  4. 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 source quantity, then write that number into the destination. Between the read and the write — even two seconds — a sale can land in the destination store. The write then blindly overwrites it, restoring a number that was already wrong, and now the destination 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 source store, 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 the destination stores’ own stock adjustments 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 drift 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.
  • 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:

  1. Contact the customer before they contact you. An email the same day reads as competence; a week of silence reads as a scam.
  2. Offer a real choice — wait for restock, substitute, or refund now. Do not pick for them.
  3. Fix the count in the source store, not the destination, or the sync will undo you.
  4. 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 destination write 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.

Two stores. One truth.

StockUnison mirrors one store's stock into every other store you connect — matched by SKU, previewed in dry run, and logged write by write.

Install on Shopify

Free plan you can stay on · live syncing from $19/mo