Kilo Courier
Live routing for a same-day grocery fleet
A courier app for 900 drivers delivering groceries in under two hours. I built the real-time dispatch channel and the driver app’s route screen, and cut battery drain enough that drivers stopped carrying power banks.
New order
14 items, 2 stops, 2.1 km
Rs 640
- Fresh Mart, Gulberg III
- House 22, Street 9, Model Town
- 900
- drivers on shift daily
- −46%
- battery use per shift
- 1.8s
- order to driver, p95
The problem
Dispatch pushed orders by polling every 15 seconds. Drivers saw jobs late, two drivers sometimes accepted the same order, and GPS tracking drained a phone before the shift ended.
Constraints
- Drivers move between 4G and dead zones constantly.
- Most drivers use budget Android phones with aggressive battery managers.
- An order must never be assigned to two drivers.
How it fits together
On the device
- Route and order screens
- Socket client with replay
- Adaptive location sampler
In the cloud
- WebSocket gateway
- Redis pub/sub and order leases
- Dispatch service
- PostgreSQL
Key decisions
One WebSocket, many channels
Replaced polling with a single socket per driver, fanned out through Redis pub/sub. Messages carry a sequence number, so the app replays anything it missed after a reconnect instead of refetching everything.
Accepting an order is a server lease
Tapping accept takes a 20-second lease in Redis. The app shows the order as pending until the lease is confirmed, which ended double assignments completely.
Adaptive location sampling
GPS frequency follows speed and distance to the next stop: every 3 seconds near a drop-off, every 30 when parked. This was most of the battery win.
Outcome
Order-to-driver time went from 9 seconds to 1.8 seconds at p95. Double assignments went to zero. Crash-free sessions rose from 97.1% to 99.6% after moving map rendering off the JS thread.
What I’d change
We underestimated Android OEM battery killers. Next time I would budget a device lab of the ten most common driver phones from week one.
Stack
- React Native
- Expo
- Reanimated
- Node.js
- WebSockets
- Redis
- PostgreSQL