Skip to main content

A walkthrough of how SKULabs reserves stock against open orders

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

warehouse linked reserves

location level reserves

Account-wide

false

n/a

Warehouse-linked

true

false

Location-level

true

true

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 id set goes into warehouse direct reserves using as key the fulfillment warehouse id and item sku

  • Items 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:

  1. Items with a fulfillment warehouse id still go into warehouse direct reserves (same as warehouse-linked).

  2. Items without a fulfillment warehouse id drop into store global location reserve maps using the store_id, channel_location_id and item sku as keys for the mapping.

  3. 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:

  1. Order created (synced or manual) — order is status: unstarted, processing: true. The next reserve recomputation includes its quantities.

  2. Inventory sync runscalculate reserved inventory system aggregates all open orders by SKU (and by warehouse / location depending on mode). The reserve map is built and cached.

  3. free is computedcalculate free map system reads location_maps for on-hand and the cached reserve map to derive free per (warehouse, item).

  4. Order picked / packed / shipped — when the shipment is created and the order moves to status: shipped, it's filtered out of the reserve aggregation (checks reserveless status list includes 'shipped', 'cancelled'). The cache is invalidated, and the next read sees that warehouse / location with one less reserve.

  5. Order cancelled or archived — same as shipped: filtered out, reserve drops.

  6. 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 into warehouse_direct_reserves[X][sku] on the next recomputation.

  • Re-routing (user changes priority warehouse, or clicks "Re-route order"): geo-routing rewrites fulfillment_warehouse_id from old warehouse Y to new warehouse Z. On the next recomputation, the reserve drops from Y and appears at Z. Y's free goes up by the order's qty, Z's free goes 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_id is set per stash item.

  • Doesn't bypass the shipped / cancelled filter — geo-routing only acts on status: unstarted, processing: true orders.


How to Change Reservation Mode

  1. Settings > Inventory > Other

  2. Order reservation method dropdown

  3. Pick Account-wide / Warehouse-linked / Location-level

  4. 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 cleared orders as no-reserve as well (in addition to shipped / 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 shipped, cancelled, or archived — or when its qty is shipped via partial shipments

Does geo-routing add or change reserves?

No. It only writes a fulfillment warehouse and then the reserve attribution follows from there

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 free calculated?

on_hand (summed across all bins) minus the reserve map for that (warehouse, item)

Did this answer your question?