Allocation engine

Updated September 22, 20264 min read

Allocation determines which fulfillment location ships which line items for an order. You control it through one of three modes.

Three modes

ModeWhenWhat runs
Pre-allocationThe create-order payload attaches fulfillment locations to the lines.Carriyo respects the upstream decision and creates fulfillment orders accordingly. The engine does not run.
Auto-allocationNo location is provided and automatic allocation is turned on for the tenant.The order allocation engine runs the pipeline below and picks a fulfillment location for each item.
Manual allocationNo location is provided and automatic allocation is off.A fulfillment order is still created. It sits in open and carries error_details with the code fulfillment_location_missing. Ops staff allocate by hand from the Dashboard.

Automatic allocation is a tenant setting, not a merchant one. It runs only when the tenant has order-management settings with enable_automatic_order_allocation set to true. A tenant without those settings has no automatic allocation at all, so every order takes the manual path.

The allocation engine

When auto-allocation runs, the engine narrows the candidate list through five stages:

1
Inventory
Find every location with stock for the order's items. Digital items are skipped.
2
Eligibility
Keep only active locations that are configured as fulfillment locations and whose coverage includes the destination address. Coverage is a set of fulfillment zones or a fulfillment radius; a location with neither serves everywhere. See Location coverage below.
3
Allocation rules
Evaluate any custom allocation rules in order. A rule either includes its target locations (discard everything else) or excludes them (keep everything else). The first matching rule wins; the engine exits with the filtered subset.
4
Prioritization rules
Apply prioritization rules in the configured sequence to break ties. Each rule maximizes one of: order fulfillment (fewest splits), location availability (most stock), or customer proximity (closest location).
5
Final pick
If multiple locations are still tied after every prioritization rule has run, the engine picks one at random.

Location coverage

Stage 2 asks one question of each location: does it cover the address this order is going to? That address is the fulfillment order's own delivery address, or its customer collection address when the delivery method is COLLECTION.

Coverage is configured on the location:

  • Fulfillment zones. The address has to match on country, state, city, or area. This is the usual setup.
  • Fulfillment radius. The location covers everything within a set distance of it. Both the location and the address need coords. Without them the location is not a candidate, so a radius location never matches an address that carries no coordinates.
  • Neither. The location serves everywhere.

Zones and a radius are alternatives rather than a pair. When a radius is set, that is what gets checked.

A collection order the customer picks up at the fulfilling location also needs that location to allow collection.

A location that is inactive, or outside coverage, is dropped before stock is read, so whatever it holds is invisible to the engine. An item that could only have come from there is reported as OUT_OF_STOCK, not as a coverage error. Check the location's status, zones and radius before you go hunting for the missing stock.

Multi-pass and split allocation

If some items remain unallocated after the pipeline finishes and split allocation is turned on for the tenant, the engine runs the pipeline again for the remaining items. This continues until every item is allocated or no candidates remain.

When items stay unallocated

Once the pipeline can no longer make progress, what happens to the leftovers turns on one tenant setting, allow_partial_order_allocation.

Partial allocation allowed. The allocated items get their fulfillment orders as normal. The unallocated remainder is split into a fulfillment order of its own with every line cancelled, so that fulfillment order lands in cancelled. The rest of the order carries on.

Partial allocation not allowed. Nothing is split off. The fulfillment order stays open, flagged auto_allocation_failed and carrying an allocation_summary. Each line reports its own allocation_failure_reason: OUT_OF_STOCK, RULE_EXCLUDED, SPLIT_NOT_ALLOWED, OUTSIDE_FULFILLMENT_ZONE, or TECHNICAL_ERROR.

Neither path cancels the Order itself.

Allocation rules vs prioritization rules

Both run inside the engine but do different jobs:

Allocation rulesPrioritization rules
PurposeFilter (narrow the candidate list)Tie-break (order the survivors)
LogicInclude or exclude based on conditionsMaximize one of: fulfillment, availability, proximity
EvaluationFirst match wins; engine exitsRun in sequence until one location remains (or the last rule runs)

Re-allocation

A fulfillment order can be re-allocated as long as it is still open or allocated:

  • The fulfillment location can be changed.
  • Lines can be moved between fulfillment orders (split or merge).
  • The fulfillment order can be cancelled and recreated.

Once pick and pack has started (processing) or the FO is fulfilled, you must restore it to open or allocated first. The path back depends on the current status:

  • From processing. Line items can be unpicked, which rolls the fulfillment order back to allocated.
  • From fulfilled. The fulfillment order is unfulfilled, which cancels the associated Shipments and rolls the lines back to allocated.

From allocated, the fulfillment order can also be released. The reservation is cleared and the lines return to open, ready for the engine (or ops) to allocate them somewhere else.

How it fits with other modules

  • Orders. Allocation is the bridge from Order to fulfillment order.
  • Inventory. Feeds stage 1 of the pipeline.
  • Locations. The targets the engine picks between.
  • Storefront. A customer-chosen delivery option can constrain which locations are eligible at stage 2.
  • Shipping. Once allocation is locked, fulfillment orders produce Shipments.