Oct 11, 2026 · Backend · 4 min read
Pricing multi-drop deliveries: splitting one route's charge across many parcels
In logistics and urban dispatch, single-order deliveries are an expensive luxury. When a rider picks up one parcel in Nairobi CBD, drives 8 kilometres to Westlands, and returns empty, unit economics collapse. To achieve profitability, platforms batch multiple deliveries into a single route—often referred to as a "tied" or multi-drop delivery.
Batching drops together makes operations efficient, but it creates a complex product and mathematics challenge: how do you fairly price and allocate costs when one trip carries orders for different merchants or customers?
If you charge every customer the full point-to-point price, you lose the competitive advantage of batching. If you split costs arbitrarily, customers with a 1 km drop subsidise someone's 15 km haul. Here is how we engineered an equitable multi-drop pricing engine in Laravel that balances fair customer pricing, predictable rider pay, and platform margins.
1. The Product Problem
Imagine a motorcycle rider starting at a hub in Industrial Area. They pick up three parcels:
- Parcel A: Heading to Upper Hill (4 km from hub).
- Parcel B: Heading to Kilimani (7 km from hub).
- Parcel C: Heading to Lavington (11 km from hub).
If priced individually, the total standalone distance might be 4 + 7 + 11 = 22 kilometres. However, the rider's actual physical route driving Hub → Upper Hill → Kilimani → Lavington is only 13 kilometres.
The total route costs less to execute than three standalone trips. How should that 13 km route charge be distributed across Parcels A, B, and C so that every customer pays less than their standalone price while the sum of individual charges exactly matches the total route revenue?
2. Haversine vs Routing APIs: Two-Tier Distance Estimation
Calling the Google Routes API or Mapbox Directions API for every pricing preview as a user drags pins around a map quickly racks up massive API bills and adds network latency. We solve this using a two-tier strategy:
- Haversine Formula for Instant Drafts: For instant previews on the mobile app or web slider, compute great-circle distance with a routing circuity factor (typically 1.3x to 1.4x in Nairobi's road layout).
- Routing Engine for Confirmed Quotes: When the merchant confirms or dispatches the batch, request the exact road route and turn-by-turn distance from the routing API.
3. Quoting the Route as a Unified Journey
Rather than calculating individual legs independently, the total cost of the route is computed as a single continuous trip: a base fare, plus the total route distance multiplied by a per-kilometre rate, plus a fixed fee for every stop after the first.
This ensures that fixed vehicle wear and dispatch costs are covered by the base fare, while riders are compensated for both the distance traveled and the dwell time required to park, verify an OTP, and hand over each parcel.
4. Proportional Cost Allocation with Largest-Remainder Rounding
To distribute the total route charge fairly, we allocate cost proportional to each parcel's standalone distance from the origin hub.
However, integer financial arithmetic creates rounding errors. If you allocate KES 850 across three parcels, simple decimal rounding might yield KES 283.33 + KES 283.33 + KES 283.33 = KES 849.99, losing a cent, or KES 850.02, overcharging the batch. We enforce the Largest Remainder Method (Hamilton–Hare) so the allocated parts always sum exactly to the route total. Work in the smallest currency unit, give each parcel the whole-number part of its exact share, then hand the few leftover units one at a time to the parcels with the largest fractional remainders.
5. Atomic Order Tying in the Database
A multi-drop order must never be partially persisted. We link the child parcel orders with a shared route batch ID and an ordered stop position, and create them all inside a single database transaction.
6. Handling Mid-Route Edge Cases
Real operations are unpredictable. Systems must be engineered for three edge cases:
- Drop Cancelled Mid-Route: If Drop 2 is cancelled while the rider is delivering Drop 1, the remaining drops preserve their original locked quoted price. The platform absorbs minor variance rather than recalculating prices for already-notified customers.
- Zero-Distance Same-Building Deliveries: When two deliveries go to the same commercial tower, assign a minimal virtual distance threshold so the allocator never divides by zero.
- Re-ordering Stops for Traffic: If road blockages require swapping stops 2 and 3, distance may shift slightly, but the pre-agreed customer invoice remains immutable.
Engineering Lessons
- Always allocate using smallest currency units (cents or cents equivalent) to eliminate rounding loss.
- Use Haversine + multiplier for high-frequency interactive previews, and full routing APIs only for final confirmations.
- Persist the tie relation atomically—either all parcels in the multi-drop route book successfully, or none do.
- Never recalculate already-invoiced customer prices if a downstream drop changes.