Skip to content
QSWEQB
hardDesignScenarioMidSeniorStaff

A three-line order could be sourced from either of two warehouses. How do you decide where it ships from, and what happens when one line falls through?

Allocation is a cost minimisation over shipping, split-parcel cost and delivery promise, evaluated per line rather than per order; the design that survives is one where every line carries its own state, cancellation is a race against the pick face, and a shortfall is a normal outcome with a defined path.

6 min readUpdated 2026-07-26

What the interviewer is scoring

  • Does the candidate write down an explicit cost function instead of naming a single rule such as nearest warehouse
  • That they hold state on the order line rather than a single status column on the order
  • Whether cancellation is treated as a request that can lose to the warehouse, not a state transition that always succeeds
  • Does the candidate say what happens to payment, promotions and shipping charges when only part of the order ships
  • Whether re-allocation after a pick failure is described as a bounded retry with an escape rather than an infinite loop

Answer

Allocation is an optimisation, so write down what you are minimising

Candidates reach for a rule - nearest warehouse, or fewest parcels - and a rule is the wrong shape of answer, because the two rules disagree constantly and neither is right on its own. Allocation is the choice of which stocking location satisfies which order line, and it is a minimisation over a cost you should be able to state.

The terms are concrete. Outbound freight, which scales with distance and weight and is usually banded rather than linear. A per-parcel handling cost, which is the reason splitting is not free even when the freight is identical. The delivery promise already shown to the customer, which acts as a hard constraint rather than a cost, because breaking it is a support contact and a refund risk rather than a few pence. Inventory position, since draining the last unit from the location that serves your densest demand region has a cost that shows up as a lost sale next week. And capacity, because a distribution centre already at its cut-off for the day cannot pick anything regardless of how close it is.

Two constraints deserve naming because they invalidate otherwise sensible plans. Some lines cannot travel together - lithium cells, aerosols, chilled goods, oversized items - so the split is decided by regulation rather than by cost. And gift wrapping, personalisation or serial-number capture may exist at only one site, which pins a line whatever the arithmetic says.

The practical structure is a candidate-generation step that lists feasible location sets for the order, and a scoring step that picks among them. This matters because it makes the trade-off visible and tunable: you can weight the promise-breach penalty up for a premium delivery tier and down for economy shipping, in configuration, without rewriting the allocator. When someone in the business asks why an order shipped in three parcels, you can answer with the scores rather than with the source code.

Splitting costs money, and the customer sees it too

A split shipment has a cost you can compute and a cost you cannot. The computable part is the extra parcel, the extra handling and the extra label. The other part is that the customer receives two deliveries, is home for neither, gets two tracking emails, and contacts support when the first parcel arrives short.

So the useful question is not whether to allow splits but who is allowed to be surprised. Two designs are defensible. You can split freely and tell the customer at the point of purchase that their order arrives in two deliveries with two dates, which costs a little conversion and buys you cheap sourcing. Or you can consolidate by moving stock between locations first, which keeps one delivery and adds a day plus an internal transfer cost. What is not defensible is splitting silently after showing a single delivery date, because you have then converted a logistics saving into a support cost and thrown away the ability to measure either.

Note that a split is also an accounting event. If shipping was charged once and promotions applied at order level, the first parcel cannot simply carry the whole shipping charge and the whole discount. Apportion order-level amounts across lines at allocation time, store the apportionment, and use it for every subsequent invoice, refund and return, or your partial refunds will not reconcile.

Cancellation is a race, and the warehouse usually wins

Cancellation looks like a state transition and behaves like a distributed race. The moment a pick list is released to the floor, an operator may already be walking towards the shelf, and your service has no authority over her feet. So model cancellation as a request with three possible outcomes rather than a mutation with one.

If nothing has been allocated, cancellation is trivial: release the reservation, void or refund the payment, done. If the line is allocated but not yet released to the warehouse, you attempt to recall it and the warehouse management system answers yes or no. If it has been picked or despatched, cancellation is not available and the honest response is to convert the request into a return, ideally with a refused-delivery or intercept option so the parcel turns round without the customer handling it.

The mistake to avoid is treating the cancellation acknowledgement as final before the warehouse has confirmed. Marking an order cancelled, refunding the payment, and then having a parcel leave the building is a worse failure than declining the cancellation, because you have now given away both the money and the goods. Confirm cancellation only on the warehouse's acknowledgement, and show the customer an in-progress state in between, unpleasant as that is.

Per-line state is the part people get wrong

Here is the specific thing that separates a design that lasts from one that gets rewritten in a year. A single status column on the order cannot represent an order where line one has despatched, line two is short-picked and awaiting re-allocation, and line three has been cancelled by the customer. Teams discover this six months in and respond by inventing composite statuses such as PARTIALLY_SHIPPED_WITH_BACKORDER, at which point the number of statuses grows combinatorially and every consumer of the order feed has to be taught the new ones.

State belongs on the line, or more precisely on the allocation of a line to a location and quantity. The order's status is then derived rather than stored, computed by rolling up its lines with a documented precedence. Derivation costs a little at read time and buys correctness permanently.

Allocation states, per line-quantity, each with a defined exit:

  pending        -> awaiting an allocation decision
  allocated      -> a location and quantity are committed, recall possible
  released       -> pick list issued; recall now requires warehouse agreement
  picked         -> physically in hand; cancellation becomes a return
  despatched     -> carrier has it; only intercept or return remain
  short          -> pick failed; needs re-allocation, substitution or cancellation
  cancelled      -> terminal, with a reason code that is not "other"

Two details make this work in practice. First, every transition is an event with a timestamp, an actor and a reason, appended rather than overwritten, because the questions you will be asked six months later are all of the form "when did this change and who changed it". Second, the reason code on short and cancelled is a controlled vocabulary, since those codes are the only way to tell a warehouse accuracy problem from a supplier problem from a customer changing her mind.

Re-allocation needs a limit and an escape

When a line goes short, the natural response is to re-allocate it elsewhere, and the natural failure is to do that forever. If two locations both believe they hold the unit and neither does, the line ping-pongs between them, accruing a promise breach at each hop while looking healthy in every individual system.

Bound it. A line gets a small number of allocation attempts, and it also gets a wall-clock deadline derived from the delivery promise, whichever comes first. On exhaustion it lands in a state that a human owns, with the options being substitution where the category permits it, backorder with a new committed date, or cancellation with compensation. Each pick failure should also decrement confidence in that location's count for that item and trigger a count, because a short pick is the cheapest inventory-accuracy signal you will ever get and most systems throw it away.

The order state machine grows teeth because reality has more outcomes than the happy path has states. Model the outcomes on the line, derive the order's status from them, and record why every transition happened - the alternative is a status enumeration that grows once per incident forever.

Likely follow-ups

  • The cheapest split ships two parcels a day apart. How do you decide whether that is acceptable?
  • A pick fails at the third warehouse in a row for the same line. What ends the loop?
  • How would you support an order where one line is a pre-order with a date six weeks out?
  • The customer cancels one line of five after two lines have shipped. Walk through the money.

Related questions

order-managementallocationsourcingpartial-shipmentstate-machine