WritingCommerce

Ship each item as it lands, hold for all, or hold until a deadline

Pick a parcel consolidation policy for multi-seller cross-border orders, fix it on the order at checkout, and release on a deadline rather than on hope.

On 3 October a customer in Dhaka places one order for three items from three sellers: a £38 phone case, a pair of trainers at £120 and a £9 USB cable. All three are addressed to your hub in New Jersey, and from there they fly to Bangladesh. The case is scanned in on 6 October and the trainers on 9 October. The cable's seller marked it dispatched on 4 October and the tracking page still says "label created". On 6 October the hub is holding one small box and has to decide whether to ship it now, wait for the other two, or wait until some date and then send whatever has turned up.

Anyone running a forwarding hub meets this on every order with more than one inbound parcel, and the choice is usually made badly because it is made in the warehouse, box by box, by whoever is holding the scanner. I have built cross-border procurement across Amazon, Alibaba, AliExpress and 1688, and the rule I apply is that the consolidation policy is a column on the order, chosen and priced at checkout before the first item lands. The warehouse executes the policy it is given; it never picks one. The counter-argument is that the warehouse knows more on the day than checkout did, and the rest of this post is the case against it.

What decides it

There are three policies worth building. Ship as it lands forwards every inbound parcel the day it is received. Hold for all keeps everything at the hub until every expected item has been scanned in, then sends one parcel. Hold until a deadline keeps items until either everything has landed or a release_by date fixed at checkout passes, then ships what is there and refunds what is not. They differ on things a checkout page, a hub and a finance team can each measure.

CriterionShip as it landsHold for allHold until a deadline
International legs per orderOne per itemOneOne, or two if an item lands after release
Time to first deliveryDays after the first item landsDays after the last item landsBounded by the deadline
Customs declarationsOne per parcel, each at its own valueOne at the combined valueUsually one
Exposure to a missing itemNone, the others have already goneUnbounded, the order never completesBounded by the deadline
Hub storage per orderHoursUntil the slowest seller deliversAt most the hold window
What checkout must showThree shipping chargesOne charge and no ship dateOne charge and a latest ship date
Refund when an item never shipsThe item only, whenever you noticeThe item, then the rest ships lateThe item, at release, automatically

The customs row needs one caution. Where a destination exempts low-value consignments from duty, splitting an order into three small parcels and combining it into one can land on different sides of the threshold. Treat that as a rule to check per destination, not a lever to pull: some authorities treat a deliberately split consignment as one, and the policy that saves duty on paper can end with the parcel held at the border and the duty billed anyway.

Ship as it lands

Best for Single-seller orders and anything the customer needs by a date

Each parcel is forwarded within a day of receipt with its own label, its own declaration and its own tracking number.

  • strengths: the customer gets the first item fastest; the hub holds no state, so there is nothing to sweep or expire; a seller that never ships costs one refund and nothing else
  • costs: three international legs for three items, each carrying the carrier's minimum charge; three declarations to prepare; the customer tracks three parcels and writes to support about the slow one

Hold for all

Best for Orders where every seller is one you have measured and trust to dispatch

Nothing leaves the hub until every expected item has been scanned in, and then one parcel goes out.

  • strengths: the lowest shipping cost per order; one declaration and one tracking number; the simplest promise to word on the checkout page
  • costs: one seller who cancels on day 12 holds the other items hostage; storage per order has no upper bound; there is no honest ship date to show the customer, because you do not know one

Hold until a deadline

Best for Multi-seller orders where cost matters more than speed

Items are held until all have landed or release_by passes; at release the hub ships what is there and the missing items are refunded without anyone deciding to.

  • strengths: one parcel in the common case; the customer sees the saving and the latest ship date next to each other; a missing item is contained by the clock rather than by a support ticket
  • costs: a release job that has to run on time and refund correctly; a second leg when an item lands the day after release; a window that has to be chosen per lane and defended when a customer asks why it is nine days
flowchart TD
  A[New order at checkout] --> B{More than one seller}
  B -- no --> S[Ship as it lands]
  B -- yes --> C{Customer paid for speed}
  C -- yes --> S
  C -- no --> D{Every seller measured reliable}
  D -- yes --> H[Hold for all]
  D -- no --> R[Hold until a deadline]:::accent
  S --> E[Store policy and release by]
  H --> E
  R --> E
Choosing the policy at checkout, from what the order already knows

Every question in that chart is answered from data the order already carries: the count of distinct sellers, the delivery speed the customer chose, and each seller's dispatch rate over its recent orders. None needs a person or a parcel that has arrived, which is why the policy can be fixed at checkout.

Where hold for all breaks

Take the Dhaka order under hold for all, with no deadline. On 6 October the case is scanned in and order_item 1 moves to received. On 9 October the trainers follow. The cable's item stays in expected, and the order stays in awaiting_items, which the customer's order page renders as "Preparing your parcel". On 12 October the marketplace cancels the cable because the seller never shipped; the cancellation arrives as a status on the marketplace order page, and nothing in the ingestion maps it onto the item row. The order still reads three expected, two received.

The customer writes to support on 14 October and again on 18 October. Support refunds the £9 by hand on 18 October, but the item is still expected, so the release check still fails and the two boxes stay on the shelf. Somebody eventually edits the row. The hub saw two parcels under one order number with no due date for twelve days; the customer saw "Preparing your parcel" for the same twelve days, then a late delivery of two items. What contains it is two things the hold for all policy does not force you to build: a terminal state per item, so a cancellation or a refund is a release trigger in its own right, and a date after which the order releases whatever its items say.

TypeScript
// simplified: decides whether the hub may ship what it holds right now
type ItemState = 'expected' | 'received' | 'cancelled' | 'lost';
type Policy = 'ship_as_it_lands' | 'hold_for_all' | 'hold_until_deadline';

interface Order {
  policy: Policy;
  releaseBy: Date | null;
  items: { state: ItemState }[];
}

function shouldRelease(order: Order, now: Date): boolean {
  const stillExpected = order.items.filter((i) => i.state === 'expected');
  if (stillExpected.length === 0) return true; // landed, cancelled or lost
  if (order.policy === 'ship_as_it_lands') return true;
  if (order.policy === 'hold_for_all') return false;
  return order.releaseBy !== null && now >= order.releaseBy;
}

The release job runs this once an hour over every order in awaiting_items. An item that moves to cancelled or lost leaves stillExpected, so the refund and the release happen in the same pass, and a job an hour late is the worst case rather than a week of silence. Under hold until a deadline, releaseBy is set at checkout from the lane's measured arrival times: if the slowest seller on the order usually lands within six days, a nine-day window catches nearly every order and still bounds the ones it does not.

Whichever policy wins, build the same four things first: a consolidation_policy and a release_by column on the order, a state on every expected item with cancelled and lost as terminal values, an ingestion step that maps a marketplace cancellation onto the item, and an hourly release job that ships and refunds from those fields alone. Once those exist, the policy is a value the checkout writes, and changing your mind about the window is a config change rather than a conversation with the warehouse.

Written by Md Nasim Anjum, senior full-stack engineer in Manchester. He builds payment orchestration, KYC and KYB compliance platforms and conversational AI.

Get in touchAll writingRSS

More writing