Inventory & stock sync
One stock pool, many channels: how availability is calculated, how buffers stop oversells, and what happens when two channels sell the last unit.
On this page
Stock is the number everyone argues about. The model here is deliberately boring: quantities live on variants at locations, and everything a channel sees is derived from them.
The four numbers
on_handintegerrequiredPhysically at the location. Changes when goods arrive, ship or are counted.
reservedintegerrequiredCommitted to orders that have not shipped yet.
availableintegerrequiredon_hand - reserved. What can still be promised to a customer.bufferintegerHeld back per channel so a slow marketplace feed cannot sell what you no longer have.
What a channel is told is available across its eligible locations, minus its buffer, floored at zero.
Why buffers exist
Marketplaces do not read your stock in real time; they accept a feed and act on it minutes later. In that window you can sell the same unit twice. A buffer is the price of that latency.
Reservations and the last-unit race
When an order is created, the units are reserved immediately, before any channel is notified. Reservation is the atomic step — everything downstream is a consequence of it.
The units are reserved against the resolved location.
available drops for every channel at once, because they all read the same pool.
Your storefront is instant. Feed-based channels are updated on their next push, which is where the buffer earns its keep.
If it arrives before the feed lands, it is accepted by the marketplace and flagged here as an oversell, with the shortfall and the suggested resolution attached. It is not silently fulfilled and it is not silently dropped.
Locations and eligibility
Every location has a type — warehouse, retail, third-party — and each channel declares which locations it can sell from. A shop's stock can be excluded from marketplace availability entirely, or included with a heavier buffer.
This is also what makes ship-from-store possible without giving marketplaces the ability to sell the shop empty.
Adjustments have reasons
Every movement is recorded with a reason: receipt, sale, return, transfer, damage, count. Nothing changes on its own.
| Reason | Effect on on_hand | Typical source |
|---|---|---|
| Receipt | Increase | Purchase order arriving |
| Sale | Decrease at fulfilment | Order shipped |
| Return | Increase after inspection | Returns flow |
| Transfer | Move between locations | Internal replenishment |
| Damage | Decrease | Manual, with a note |
| Count | Set absolute | Stocktake |
A stocktake sets the absolute number and records the delta, so the difference between what you thought and what you had is itself a reported figure.
Low stock and replenishment
Thresholds are set per variant per location, and breaching one raises an event you can act on — a notification, a purchase order draft, or a webhook into whatever your buying team already uses.
Next: Channels overview, where this availability turns into listings.




