Retail & e-commerce

Cutting failed deliveries by more than half by fixing the address, not the map

An order state machine, delivery slots tied to real rider capacity, and a customer app and a rider app built for the phones and networks people actually have, not the ones a demo runs on.

On-time delivery rate
low seventies → low nineties, percent
Failed first-attempt deliveries
cut by more than half
Repeat purchase share via the app
roughly tripled
Sector
D2C retail & quick commerce
Estate
~40 dark stores/hubs across 3 metros
Engagement
Product build, then a retained pod
Duration
10 months to first market, ongoing

Stack

  • Flutter
  • NestJS
  • PostgreSQL
  • Redis
  • Kafka
  • OSRM routing
  • Google Maps Platform
  • Razorpay
  • Kubernetes

Practices involved

Discuss a similar problem

The situation

The retailer's stack had grown by accretion: a storefront plugin, order tracking in a shared spreadsheet once a marketplace integration fell over, and delivery handled by whichever local courier picked up the phone that day. There was no owned customer app, so no push notification, no saved address, and no channel for a second order that did not go back through a marketplace taking a cut of it.

The constraint

Two things made a straightforward rebuild the wrong plan. First, a delivery promise like "in 90 minutes" has to reflect the rider capacity and stock actually available from the nearest hub at that moment, not a flat radius on a map — overpromising a slot was the single biggest driver of bad reviews before we started. Second, addresses in the markets served are frequently informal — a landmark and a floor number, not a reliable postal code — and a failed delivery costs a return trip, a frustrated rider and a customer who does not order again.

What we built

Order orchestration as the source of truth

One order state machine spans cart, payment, pack, dispatch, delivery and returns, replacing three disconnected systems. Every state change is an event; the customer app, the rider app, the hub dashboard and finance subscribe to it rather than polling three different sources that used to disagree.

Slot promising tied to real capacity

Delivery slot availability is computed from live rider capacity, hub inventory and a real drive-time matrix, recomputed as conditions change, rather than a static radius set once at launch.

Address resolution that assumes the address is wrong

Customers drop a map pin and add a landmark note; the rider app shows both, and a reusable "last 200 metres" note attaches to the saved address for next time. Most of the reduction in failed first attempts came from this, not from a better map provider.

A rider app for the phones people actually carry

Offline-first, with a local queue of assigned stops and opportunistic sync, running acceptably on low-end Android devices, because a meaningful share of the delivery fleet uses hand-me-down phones on patchy data. Cash-on-delivery collections log against the order automatically and reconcile at day close instead of on a whiteboard.

A customer app built around the second order, not the first

Push-driven reorder flows, live tracking with a recalculated ETA instead of a static countdown, and saved addresses that get more accurate every time they are used.

What changed

On-time delivery moved from the low seventies into the low nineties, percentage-wise, and failed first attempts fell by more than half, mostly from the address work rather than routing changes. The app now carries a meaningful share of orders as repeat purchases, which is revenue the retailer keeps instead of paying a marketplace for it a second time.

What we would do differently

The first rider app version polled GPS location every five seconds to keep tracking smooth. It drained batteries within a shift, and riders started quietly turning the app off mid-route, which silently broke tracking for exactly the deliveries where it mattered most. We moved to adaptive, event-driven location pings in month four. Battery and data budget should have been a stated constraint from day one, not something we learned from riders switching the app off.

Outcomes

On-time delivery rate
low seventies → low nineties, percent
Failed first-attempt deliveries
cut by more than half
Repeat purchase share via the app
roughly tripled

Client identity withheld under a mutual NDA. Figures are illustrative — rounded and directional, meant to show the shape of the change rather than an audited result. We will walk through the real numbers, and how they were measured, under NDA on a call.

Next step

Tell us what you're trying to ship.

Send the brief, the RFP, or three messy sentences about the problem. You get a written point of view from an architect within two working days — not a sales deck.