1. Blog
  2. System breakdown

System breakdown: the rider dot that moves across your map

A delivery app shows the rider moving toward your door every few seconds. Here is the path one location update takes, and the three choices that keep it cheap.

The Kolom team4 min read

You order groceries from the Mangrove app. Ten minutes later a small dot starts moving along the map toward your building. It feels live, but it is a chain of small, boring steps that repeat every few seconds. Each step has a cost, and each one can fail.

Mangrove Market has about 600 riders. On a festival evening most of them are on the road at once, and each rider app sends its position every 4 seconds. That is about 150 location updates per second. The number is small for a server, but the design choices around it decide whether the feature costs a few dollars a day or a few hundred.

The path of one update

Rider app Location API Redis Customer every 4 s keep latest push
One update: the rider app posts a position, the API overwrites the rider's latest position in Redis, and pushes it to the customer who is watching that order.
  1. The rider app sends a small message: rider id, order id, latitude, longitude, a timestamp. About 100 bytes. It uses the rider's mobile data, so it should be small and it should not wake the radio more often than needed.
  2. The API keeps only the latest position. It writes one key per rider in Redis, for example rider:381:pos, and overwrites it each time. Nobody needs every point to draw a dot. If you also want the route history for disputes, append it to a cheap log or a time-series table in batches, away from the hot path.
  3. The API pushes the update to the customer who is watching. The customer app keeps one open connection while the order screen is visible. When the rider's position changes, the server sends it down that connection.

Three choices that keep it cheap

Push, then fall back to polling. If the customer app asked the server for the position every 4 seconds, most answers would be "same as before", and each one costs a request. An open connection (WebSockets or Server-Sent Events) lets the server speak only when something changed. Phones lose connections all the time, so the app reconnects with a delay that grows after each failure, and while it is reconnecting it can poll every 15 seconds. The lesson Real-time updates compares polling, WebSockets, SSE and push notifications in detail.

Move the dot smoothly on the phone. Updates arrive every 4 seconds, yet the dot glides. The customer app animates between the last two positions. That is free: no extra requests, and the map feels live even on a slow network. When an update is late, the app slows the dot down instead of jumping it backwards.

Send less when nothing changes. A rider waiting at a store for the bags does not need to report every 4 seconds. The rider app can send an update when the position moves more than about 20 metres, or every 30 seconds while standing still. On a busy evening that cuts the traffic a lot, and it saves the rider's battery.

Questions to ask in your next review

  • What does the customer see when the rider's phone loses signal for a minute? A frozen dot, a "last seen 1 minute ago" label, or nothing?
  • Who is allowed to see a rider's position, and when does that stop? It should end when the order is delivered.
  • How many open connections does one server hold, and what happens to them during a deploy?

If you want to build this idea yourself, the lessons on caching and queues and pub/sub cover the two building blocks, and the Uber case study shows the same pattern at a much bigger scale.

system designreal-timemobile

Get the next one by email