Skip to content

Stock Reservations

In addition to routing, the per-delivery app is responsible for placing and releasing stock reservations against the SKU actor as deliveries progress through their lifecycle. This is what makes "the order is committed; the warehouse must hold the stock" a real, durable claim that other orders cannot accidentally over-allocate.

One source of truth

Reservations live on the SKU actor — the same place that tracks physical stock. The routing app sends messages to the SKU actor whenever a reservation needs to change; the actor handles the bookkeeping. No reservation data lives on the order itself.

When reservations are placed

Reservations are placed when a delivery is in open or processing state and has a real inventoryKey (not "auto_assign" and not empty).

Delivery stateHas real inventoryKey?Reservation behaviour
openYesReserve quantity × unit-quantity against that warehouse, per SKU on the line.
processingYesSame — reservation is preserved across the open → processing transition.
completedYesUnreserve and subtract from physical stock (warehouse picked the items).
cancelled(any)Unreserve. No physical stock change.
open / processingNo (auto_assign or empty)No reservation — there's no real warehouse to reserve against.

These rules apply uniformly across the original delivery and any extra deliveries the routing app creates during a split.

Lifecycle diagram

What triggers a reservation update

The app diffs reservations after every order change:

  1. Add an order line, increase quantity → reservation grows.
  2. Remove an order line, decrease quantity → reservation shrinks.
  3. Change a delivery's inventoryKey from warehouse A to warehouse B → unreserve A, reserve B (treating it as one atomic operation, so other orders see no transient drop).
  4. Set inventoryKey back to auto_assign → unreserve everything for the delivery. The app then re-routes on the same hook firing and places fresh reservations against the resolved warehouse.
  5. Delete the order (the rare destructive case) → fires the OnOrderDeleted hook variant; the app unreserves everything across all deliveries.
  6. Stock arrives at the back-ordered warehouse, or another order releases stock → the SKU actor automatically promotes outstanding back-order entries to reservations against the freshly available stock. No routing app involvement needed.

Reservations and split lines

When the app splits an order line across warehouses, the reservations follow the split:

  • The original order line keeps reservations against the original delivery's warehouse for its remaining quantity.
  • Each new order line (with its own orderLineId) carries reservations against its own warehouse.

This means a splitOrderLine operation has implicit reservation movement — units that were notionally reserved against the original delivery's warehouse get rebalanced. The SKU actor's view of "open reservations" stays accurate throughout.

Reservations against insufficient stock

The app always sends a reservation request for the full demand — it never caps the request at available stock.

The SKU actor handles the shortfall by splitting that single request into two kinds of records:

  • Reservations for as much as physical and incoming stock can cover. Total reservations never exceed available stock, so availableStock floors at zero rather than going negative.
  • A back-order entry for the remainder, linked to the same reservation request.

Both kinds of records hang off the same reservation request and are queryable on the SKU graph, so consumers can see exactly which portion of a request is fulfilable today and which portion is waiting on stock.

For the operator implications and how back-orders feed procurement and replenishment, see Back-Orders.

Observability

Reservations are queryable via the standard SKU actor graph:

  • asset.product.sku nodes carry availableStock, physicalStock, and reservedStock fields.
  • Each SKU has reservation entries that link back to the originating order line.

So you can answer questions like "what orders are reserving stock at warehouse X for SKU Y?" with a normal graph query.

Inventory date and reservations

The inventory date on a delivery affects the stock lookup the app uses when deciding what to reserve. It does not change reservation behaviour itself — reservations are always placed now against the resolved warehouse.

So if a delivery has inventoryDate = today + 14 days:

  1. The app counts physical stock + incoming-by-day-14 shipments when deciding what to route.
  2. It places reservations today against the resolved warehouse.
  3. The reservation is held until the delivery is completed or cancelled.

If the incoming shipment fails to arrive, the units originally reserved against that shipment are converted to back-order entries when the SKU actor next recalculates — surfacing the gap as explicit, queryable data instead of a silent failure.

See also

© 2024 Hantera AB. All rights reserved.