A walkthrough of how SKULabs reserves stock against open orders, the three reservation modes available, what happens to reserves over an order's lifecycle, and a short clarification on how geo-routing fits in (spoiler: geo-routing does not change how reservations work — it only changes which warehouse a reservation lands in).
What a "Reservation" Is
When an order is created and is still open (not shipped, not cancelled), the quantities on its line items are subtracted from available stock so other orders / sync cycles don't oversell that inventory. The on-hand number doesn't change — only free (a.k.a. "available") changes.
Formula:
free = on_hand - reserved
on_hand comes from the location_maps collection (one document per (warehouse, bin, item)).
reserved comes from a recomputation across all open orders.
The reserve count is not stored anywhere — it's recomputed on demand and cached for 5 minutes.
The Three Reservation Modes
Configured under Settings > Inventory > Other. Stored as two booleans on account inventory:
Mode |
|
|
Account-wide |
| n/a |
Warehouse-linked |
|
|
Location-level |
|
|
Location-level builds on top of warehouse-linked — you can't have location-level without warehouse-linked.
Mode 1 — Account-Wide
The simplest model. All open-order reserves are summed by SKU and subtracted from total on-hand across the whole account. Every store sees the same free number for the same SKU.
Example:
You have:
Warehouse A: 100 units of SKU-100
Warehouse B: 50 units of SKU-100
Total on-hand: 150
Order #1 from Store X reserves 10 units of SKU-100.
Order #2 from Store Y reserves 5 units of SKU-100.
reserved = 15 free = 150 - 15 = 135
Both Store X and Store Y see free = 135 for SKU-100. It doesn't matter which warehouse will physically ship — the reserve is pooled.
Mode 2 — Warehouse-Linked
Reserves are tracked per warehouse using the line item's fulfillment warehouse id. If the order's stash item is assigned to Warehouse A, the reserve counts against Warehouse A only.
Example — same setup as before:
Warehouse A: 100 units of SKU-100
Warehouse B: 50 units of SKU-100
Order #1 has fulfillment_warehouse_id = A, qty 10.
Order #2 has fulfillment_warehouse_id = B, qty 5.
warehouse_reserves_map > A > SKU-100 = 10 → free at A = 100 - 10 = 90 warehouse_reserves_map > B > SKU-100 = 5 → free at B = 50 - 5 = 45
What gets sent to each store depends on which warehouses that store is linked to (Settings > Inventory > Stock Sync). If Store X is only linked to Warehouse A, Store X sees free = 90. If Store Y is linked to both, Store Y sees free = 90 + 45 = 135.
Where the per-warehouse attribution comes from:
Each line item with a
fulfillment warehouse idset goes intowarehouse direct reserves using as key the fulfillment warehouse id and item skuItems without a
fulfillment warehouse id(unassigned) drop into a per-store bucket and get spread across warehouses linked to that store
Mode 3 — Location-Level
Builds on warehouse-linked by adding a second bucket: per-channel-location reserves. This is meant for sellers who use multi-location channels (Shopify, Square) and want stock at one location not to deplete inventory shown at another location, even within the same store.
The model:
Items with a
fulfillment warehouse idstill go intowarehouse direct reserves(same as warehouse-linked).Items without a
fulfillment warehouse iddrop intostore global location reserve maps using the store_id, channel_location_id and item skuas keys for the mapping.When computing per-warehouse reserves, the location bucket is distributed across the warehouses linked to that channel location.
Example:
Shopify Store has two locations: "Downtown" (linked to Warehouse A) and "Mall" (linked to Warehouse B). SKU-100 has 100 units in A and 50 units in B.
Order #1 placed at "Downtown" location, qty 10, not yet routed (no fulfillment_warehouse_id):
store_location_reserve_maps[shopify_store][downtown_location_id][SKU-100] = 10 → This 10 only counts against Warehouse A (linked to Downtown): free at A = 100 - 10 = 90 free at B = 50 - 0 = 50
The "Mall" location's stock at Warehouse B is untouched. Compare with warehouse-linked mode where the unassigned reserve would have spread across both A and B.
Caveat: if Downtown is linked to multiple warehouses (say A and C), the location-level reserve still spreads across both — it narrows the reservation from "all store warehouses" to "all warehouses linked to this channel location."
Order Lifecycle and Reservation Flow
What actually happens to reserves as an order moves through the system:
Order created (synced or manual) — order is
status: unstarted,processing: true. The next reserve recomputation includes its quantities.Inventory sync runs —
calculate reserved inventorysystem aggregates all open orders by SKU (and by warehouse / location depending on mode). The reserve map is built and cached.freeis computed —calculate free mapsystem readslocation_mapsfor on-hand and the cached reserve map to derivefreeper (warehouse, item).Order picked / packed / shipped — when the shipment is created and the order moves to
status: shipped, it's filtered out of the reserve aggregation (checksreserveless status listincludes'shipped','cancelled'). The cache is invalidated, and the next read sees that warehouse / location with one less reserve.Order cancelled or archived — same as shipped: filtered out, reserve drops.
Order partially shipped — the per-shipment quantities are subtracted from the per-order reserve so we don't reserve what's already physically shipped
The reserve map has a 5-minute TTL but is invalidated immediately on any event that changes order state.
Where Geo-Routing Fits
Geo-routing does not change the reservation model. It changes one field on each stash item — fulfillment_warehouse_id — which is the same field warehouse-linked / location-level modes already key reserves on.
Concretely:
Before geo-routing runs: an item may have no
fulfillment_warehouse_id(just-synced order). In warehouse-linked mode, its reserve goes into the store-level bucket. In location-level mode, it goes into the channel-location bucket.After geo-routing runs: the item now has
fulfillment_warehouse_id = X. Its reserve moves intowarehouse_direct_reserves[X][sku]on the next recomputation.Re-routing (user changes priority warehouse, or clicks "Re-route order"): geo-routing rewrites
fulfillment_warehouse_idfrom old warehouse Y to new warehouse Z. On the next recomputation, the reserve drops from Y and appears at Z. Y'sfreegoes up by the order's qty, Z'sfreegoes down by the same.
So the team can think of it this way: the reservation system always reads fulfillment_warehouse_id from the order. Geo-routing only writes that field. No special integration — re-routing is "free" because reserves are recomputed from current order state every time.
The reserve cache is invalidated whenever the order document changes, which includes geo-routing's updates, so the next inventory read reflects the new assignment.
What geo-routing does NOT do
Doesn't switch reservation modes.
Doesn't split reserves manually — the reserve aggregation does that automatically based on whatever
fulfillment_warehouse_idis set per stash item.Doesn't bypass the
shipped/cancelledfilter — geo-routing only acts onstatus: unstarted, processing: trueorders.
How to Change Reservation Mode
Settings > Inventory > Other
Order reservation method dropdown
Pick Account-wide / Warehouse-linked / Location-level
Save
Existing reserves are recalculated using the new mode on the next inventory sync. There's no migration needed — reserves are always derived from current order state.
Common Pitfalls / Gotchas
Reserves drift if a flag changes mid-day: Switching modes invalidates the cache, but if the dropdown is changed while orders are mid-flight, expect a brief window where some places still show old values until cache TTL expires.
Manual orders without a channel location fall back to the per-store bucket in location-level mode (no channel location to bucket against). This is documented behavior, not a bug.
Overshipped orders are protected against under-reserving: per-order net-reserve is
Math.max(reserves - shipped, 0). An order that ships more than ordered won't push reserves negative.Per-scan deduction mode treats
clearedorders as no-reserve as well (in addition toshipped/cancelled).
Quick Cheat Sheet
Question | Answer |
How do I know which mode is active? | Go to Settings > Inventory > Settings > Order reservation method |
When does a reserve "go away"? | When the order moves to |
Does geo-routing add or change reserves? | No. It only writes a |
What happens to a reserve on re-route? | The reserve "moves" from old warehouse to new warehouse on the next recomputation. No manual transfer step |
How is |
|
