Engineering Deep Dive

Ranking 13 Warehouses in Under a Second

How a checkout-time routing engine classifies order lines, rates candidate warehouses in parallel, consolidates shipments, and falls back to internal ranking when the carrier API goes down.

Updated September 2026 ยท About a 6 minute read

Private employer Details are sanitized; architecture and outcomes are described without proprietary identifiers.

TL;DR

  • Every checkout has to pick which of 13 warehouses ship an order, from live carrier rates and inventory that is partly computed, inside a synchronous PHP request.
  • Rating candidates one at a time took seconds; issuing every rating call at once collapsed the wait to roughly the slowest single call.
  • Checkout processing fell by over 75 percent, and a distance-based fallback kept checkout available through carrier outages.

Context

A wholesale e-commerce operation fulfills orders from a network of 13 active warehouses spread across the country. Every order that reaches checkout forces the same question: which warehouse, or which combination of warehouses, should ship this? The lazy answer, ship each line from its default location, quietly costs money on every order. It produces split shipments when one building could have covered everything, pays higher rates than necessary, and makes delivery slower than it needs to be.

The good answer needs two things that are expensive to get: real shipping rates for this specific order from a carrier, and a truthful picture of what each warehouse can actually fulfill right now. Neither lives in the checkout code. Rates live behind a third-party API, and inventory truth lives in a legacy database where some products do not even hold their own stock.

And the decision has to happen during checkout, in real time, while a customer is watching a spinner. That latency budget, more than anything else, shaped the system.

Constraints

  • A synchronous, legacy runtime. The engine runs inside a PHP request against an IBM DB2 backend. There is no async runtime or job queue to push the work onto; whatever the routing decision costs, the checkout request pays it.
  • A third-party dependency in the hot path. Real cost and transit data only comes from the carrier's rating API. Its latency and uptime are outside the system's control, and checkout was not allowed to fail just because a third party was having a bad day.
  • Inventory that is not where it looks. Kits and custom-cut items hold no stock of their own. Their availability is computed recursively at request time from the stock of their parent components, so "is this in stock at warehouse X" is itself a calculation, not a lookup.
  • Business rules that override optimization. Vendor-shipped items must stay out of consolidation entirely, backordered lines get isolated to primary distribution hubs, and will-call orders split into an immediate local pickup plus a consolidated remainder. The optimizer only gets to optimize what the rules leave it.

Options considered

Option A: rate warehouses one at a time. The straightforward implementation loops over candidate warehouses and calls the rating API for each. It is correct and easy to reason about, and it is exactly the shape the latency problem came from: each call costs a full network round trip, and the round trips stack linearly. A dozen candidates means checkout waits on a dozen sequential API calls. At real traffic this was measured in seconds, which is an eternity in a checkout flow.

Option B: precompute a rate matrix offline. Ranking every warehouse against every destination zone on a schedule would make checkout a pure lookup and take the carrier out of the hot path entirely. It lost on accuracy: real rates depend on the specific order in front of you, its weight, dimensions, and service level, and the ranking depends on live stock. A stale matrix does not fail loudly; it picks a confidently wrong warehouse, and the cost shows up later as a split shipment nobody can explain.

Option C: skip the carrier and rank by geography. Ranking candidates by distance to the destination is fast and has no external dependency, but it is blind to what shipping actually costs and how long it actually takes. It lost as the primary strategy, then won a different job: it became the fallback. When the rating API is down, a dependency-free ranking that is roughly right beats a checkout page that is precisely unavailable.

The chosen design keeps live rating for its accuracy and attacks the waiting instead: issue every rating call at once.

The design

The pipeline runs in four stages. First, the destination address passes through a normalization layer that sanitizes and formats the geographic data, because a malformed address fails rate requests and address validation downstream. Second, every order line is classified against the business rules: vendor-shipped lines exit the flow, backordered lines are pinned to primary hubs, will-call pickups split off, and availability for kit and custom-cut lines is resolved recursively through their parent components. Only the lines that genuinely need a shipping decision continue.

Third, the ranking core does the thing the whole design exists for: it issues one rating request per candidate warehouse concurrently, using parallel cURL, instead of one after another. The wall-clock cost of rating the network collapses from the sum of all calls to roughly the slowest single call, which is what brought complex warehouse ranking to sub-second response times. Fourth, ranked candidates are consolidated: if one warehouse can cover the whole remaining order it wins outright, and otherwise lines are grouped dynamically to cover the order with the fewest, cheapest shipments the rules allow.

Checkout ordercustomer waitingNormalize, classifydropship, backorder, will-callone call per warehouse, in parallelCarrier rating APIthird partyon failureInternal rankingno external callsrated candidatesRank, consolidatefewest shipments winFulfillment plansub-second

The checkout-time routing flow, from raw order to fulfillment plan. Use "Next step" to walk through it.

The routing flow: an order is normalized and classified, candidate warehouses are rated through the carrier API in parallel, and results are ranked and consolidated into a fulfillment plan. On carrier failure, a dependency-free internal ranking takes over so checkout still completes.

The failure path is a first-class part of the design rather than an afterthought. The engine detects rating failures and switches to the internal fallback ranking, so an outage upstream degrades the quality of the routing decision instead of the availability of checkout. That distinction, degrade the answer rather than the service, is what kept fulfillment at 100 percent availability through third-party outages.

What happened

The concurrent architecture cut checkout-phase processing time by over 75 percent compared to the sequential approach, and warehouse ranking held at sub-second response times. When the carrier API did go down, checkout kept working on the fallback ranking, which is the outcome the availability requirement existed to protect.

The honest tradeoffs: fanning out in-request still ties checkout latency to the slowest single external call, and it multiplies request volume against the carrier API on every checkout. Concurrency bought speed, but the availability guarantee never came from the fan-out; it came from being willing to serve a rougher answer when the accurate one was unreachable. The rule set is the other cost. Dropship exclusions, backorder isolation, and will-call splits each entered the engine as branching logic, and that kind of logic compounds quietly in a legacy codebase.

That compounding is visible in what came after: the same allocation and consolidation semantics were later extracted into a dedicated order pipeline (covered in the Enterprise Orders API case study on this site), where every line carries an explicit type instead of being implied by branching. Done again from scratch, that structure would be there from day one. The routing logic outlived its first home, which is usually the sign it was the right logic.

Next deep dive

Porting 1,000 Lines of Order Logic Without Guessing

How a strangler cutover from a legacy .NET order pipeline to Bun and Postgres is de-risked by an executable parity harness: same payloads through both implementations, JSON-diffed until they agree.

About a 6 minute read