InterviewKata
System design · Worked design D25 of 46 · Location and marketplaces · Long form

Design maps and navigation

Show anyone a map of anywhere, find the fastest way from A to B across a continent in well under a second, and keep the arrival time honest as traffic changes. Three hard parts hide in that sentence: a graph with hundreds of millions of road segments, a stream of millions of location pings a second, and a prediction (the ETA) that users check against reality every time.

1. The prompt

"Design a maps app: people can look at the map, get driving directions with an arrival time, and be guided turn by turn, with the route updated when traffic changes."

What makes it hard:

2. Frame the problem

Which modes: driving, walking, cycling, public transport?

Driving first. Walking and cycling later; public transport is out of scope.

Driving routes depend on live traffic; transit is a timetable problem with different algorithms. One mode keeps the design focused.

Whole world, or one country?

Whole world.

The road graph can't sit on one machine's search in reasonable time, and data has to live near users: regions and partitioning become central.

How many users?

About 1 billion monthly users; at peak around 10 million people are navigating at once.

Navigating phones send location every few seconds: that stream, not route requests, is the biggest write load.

Must routes use live traffic?

Yes, and arrival times should be accurate: within about 10% for most trips.

Live traffic means edge weights change constantly, which rules out routing structures that take hours to rebuild.

Should a route update while I'm driving?

Yes: reroute if you miss a turn or a faster route appears.

Navigation is a long-lived session, not a single request: the server needs a channel back to the phone.

Does it need to work with a poor connection?

It should keep guiding you through tunnels and dead zones.

The phone must hold the route and the map tiles for it locally; the server is an advisor, not a remote control.

Search for places too?

Basic search by name and address, yes. Reviews and photos, no.

Geocoding (text → coordinates) is a search index plus geohash cells (Module 12); keep it small.

Privacy rules for location data?

Traces must not identify people; keep them only as long as needed.

Traffic needs speeds per road, not who drove where: aggregate and drop identities early.

3. What it must do

  1. A user can view the map anywhere, panning and zooming smoothly.
  2. A user can get a driving route from A to B with an arrival time, using current traffic.
  3. A user can navigate: follow the route turn by turn, with rerouting when they leave it or traffic changes.

Not now: public transport (a timetable problem), reviews and photos (a separate content system), Street View imagery (a blob pipeline), offline downloads of whole regions (a follow-up in section 10).

4. How well it must do it

TargetWhy this number
Map tiles: p99 under 200 ms anywhere speed · where it runsPanning must feel instant; slow tiles are the first thing users notice.
Routes: p99 under 1 s, even across a continent speedUsers tap "Directions" and wait; a second is the ceiling.
ETA accuracy: within 10% of the real trip time for 90% of trips data qualityThe ETA is the product's promise; users compare it with reality.
Traffic freshness: a new jam affects routes within 2 minutes load shapeRouting into a jam that started five minutes ago is the failure users remember.
Navigation keeps working through server or network trouble surviving failuresA driver mid-trip can't be left without directions.
Location privacy: no stored trace identifies a person security and privacyLocation history is among the most sensitive personal data.

5. Numbers that change the design

QuantityWorking→ so we…
Road graphHundreds of millions of intersections and road segments worldwide; a continent alone is tens of millionsPlain Dijkstra on a long trip explores millions of nodes (seconds) → so we precompute shortcuts and answer in milliseconds
Map tilesZoom level z has 4z tiles; at z = 18 that's about 69 billionMost are ocean or never viewed → so we pre-build low zooms, build high zooms on demand, and cache everything at the CDN
Location pings10 M navigating phones × 1 ping every 5 s~2 M pings a second → so ingestion is a partitioned stream, aggregated per road segment per minute, never a database write per ping
Route requests~100 M routes a day ÷ 10⁵ ≈ 1,000/s, ~5,000/s at peakModest → so a few hundred routing servers holding the graph in memory are enough; the cost is per query, not the count

Skip estimating place-search traffic: it's an ordinary search index (Module 12) and won't change the design.

6. The nouns

segments      segment_id, from_node, to_node, length_m, road_class, speed_limit, one_way, cell_id
segment_speed segment_id, minute, avg_speed_kmh, sample_count               (live, per minute; history by time of week)
tiles         z, x, y, version → object key in blob storage                  (served through the CDN)
trips         trip_id, user_id, route_id, started_at, status                 (short-lived; no raw trace stored)

7. The contract

REST for one-off requests, a streaming connection for navigation. The user comes from the auth token.

GET  /v1/tiles/{z}/{x}/{y}.mvt?v={version}     → vector tile        (cached at the CDN for days)
GET  /v1/places?q=&near=lat,lng                 → [{place_id, name, lat, lng}]
POST /v1/routes  {origin, destination, depart_at?, avoid?}
     → {routes: [{route_id, polyline, distance_m, eta_s, steps: [...]}]}  (best + up to 2 alternatives)
POST /v1/trips   {route_id}                     → {trip_id}
WS   /v1/trips/{trip_id}/stream   client → {lat, lng, speed, heading, ts} every ~5 s
                                  server → {eta_s} | {reroute: {route}} | {alert}

Data flow for traffic: phones send pings → ingestion → a stream partitioned by region → snap each ping to a road segment → average speed per segment per minute → new edge weights for routing → better routes and ETAs.

8. First working version

A CDN and tile store, a place search index, one routing service holding a region's graph in memory, and a navigation service.

8.1 Viewing the map

The app asks for the tiles covering the screen. Tiles are pre-built and stored as objects (Module 10); the CDN answers almost every request. Vector tiles carry roads and labels as data, so the phone draws them at any rotation and style.

8.2 Getting a route

Geocode the destination, then run a shortest-path search on the road graph, where each segment's weight is its travel time. The first version runs A* (Dijkstra guided towards the destination) on the region's graph in memory.

8.3 Navigating

The phone downloads the route and the tiles along it, then guides the driver locally. Every few seconds it streams its position; the server compares it with the route and recomputes the ETA.

Parked for laterA* on a continent is too slow (9.1) · the world's graph doesn't fit one machine (9.2) · weights ignore live traffic (9.3) · the ETA is just distance ÷ speed limits (9.4) · reroutes and dead zones (9.5) · tiles for the whole planet (9.6).

9. Make it hold up

9.1 Fast routes on a continental graph routes under 1 s

ApproachWhy
✗ BadDijkstra over the whole graph for every requestExplores in all directions: millions of nodes for a long trip, seconds of CPU per route.
~ GoodA* or bidirectional searchSearches towards the target (or from both ends), several times fewer nodes. Still too slow coast to coast.
✓ GreatPrecomputed shortcuts: contraction hierarchies or multi-level partitions. Offline, add "shortcut" edges that skip minor roads; a query then climbs from local streets to highways and back down, touching only hundreds to thousands of nodesMilliseconds per route. The catch: classic contraction hierarchies take a long time to rebuild when weights change, so traffic needs the variant in 9.3.

This is the move interviewers look for: trade offline preprocessing for fast queries, the same idea as an index. Open-source engines (OSRM, Valhalla) and the Customizable Route Planning work from Microsoft Research show it works at continental scale.

9.2 Splitting the world routes under 1 s · surviving failures

9.3 Live traffic from location pings traffic within 2 minutes · privacy

9.4 Honest arrival times ETA within 10%

ApproachWhy
✗ BadDistance ÷ speed limitIgnores traffic lights, turns and congestion; always optimistic.
~ GoodLive speeds per segment, summed along the routeRight now, but wrong for a 2-hour trip: by the time you reach the far segment, its traffic has changed.
✓ GreatLive speeds near you, historical speeds by time of week further away, corrected by a learned model trained on completed tripsPredicts the traffic you'll meet when you get there. Measure error per region and road type every day.

9.5 Navigation sessions and rerouting keeps working

9.6 Tiles for the whole planet tiles under 200 ms

9.7 The whole design after the deep dives

10. Interviewer follow-ups

Users want offline maps for a whole region.

Package the region's vector tiles, place index and routing graph (with its precomputed shortcuts, but static historical speeds) as a downloadable bundle, updated weekly. The phone routes locally; online, it still asks the server for traffic-aware routes. Bundles are versioned files on the CDN.

Add public transport.

A different problem: routes depend on timetables, so the graph is time-dependent. Algorithms built for timetables (scanning connections or rounds of trips) answer in milliseconds; live vehicle positions adjust departures. It's a separate service sharing places and tiles.

A new motorway opens tonight.

Map edits go through a validation pipeline into the next graph build. The affected cells are re-partitioned and re-customised, routing servers load the new version side by side and switch atomically, and the changed tiles get new versions. Rolling back means switching to the previous version.

One region's data centre goes down.

Routing servers for each region run in several zones and a second region holds a copy of the graph. Navigation continues on phones regardless; route requests fail over to the other region with slightly staler traffic.

How do you keep location data private?

Drop user IDs at ingestion; use rotating trip tokens; discard the first and last few hundred metres of each trace so homes aren't revealed; publish only segment speeds with enough samples; delete raw pings within hours.

ETAs are consistently 15% optimistic in one city.

That's model bias: compare predicted and actual times per city, road type and hour. Likely causes: a new road layout, events, or speeds from too few samples. Retrain with recent trips and add the city's error to the dashboard.

Traffic during a public holiday breaks the predictions.

Historical patterns assume a normal week. Treat holidays as their own time-of-week profiles, and lean more on live speeds when they diverge from history.

10× more users.

Tiles scale with the CDN. Routing scales with more replicas per region. Ping ingestion scales with partitions; aggregation is per segment, so it parallelises. The overlay graph stays small.

Show the three best routes, not one.

Find alternatives that are meaningfully different (share less than, say, 70% of their length) and not much slower, using penalties on the first route's segments and re-searching. Precomputed shortcuts keep each search cheap.

How would you test a routing change?

Replay a large set of real trips offline, compare route time and ETA error against the current version, then shadow-route a slice of live traffic before a gradual rollout.

11. When things break

FailureWhat users seeHow we detect itWhat limits the damage
Traffic pipeline stallsRoutes ignore new jamsAge of the newest segment speedsFall back to historical speeds; alert when data is over 5 minutes old
Bad graph build (missing road)Strange detoursOffline replay comparison before rollout; route-length anomaliesVersioned graphs, staged rollout, instant rollback
Routing servers overloadedSlow "Directions"Route latency p99, queue depthAutoscale replicas; shed alternative-route computation first
CDN or tile store issueBlank map squaresTile error rate by regionSecond CDN; phones cache recently viewed tiles
Phone loses signalNothing, ideallyStream disconnectsRoute and tiles held locally; reconnect and resume
GPS noise in city canyonsWrong-street jumpsMap-matching confidenceHold the last good match; combine with heading and speed

12. Wrap-up and the clock

Trade-offs we made:

What we'd watch: route latency p99 · ETA error by region · traffic data age · tile error rate · reroute rate and acceptance · ping ingestion lag.

At 10×: more routing replicas per region; more stream partitions; tighter aggregation windows only where traffic is dense.

A 60-minute interview

0–5Frame: modes, world scale, live traffic, rerouting
5–10Must do, how well, the graph and ping numbers
10–15Nouns, contract, traffic data flow
15–25First version: tiles, route, navigate; parked list
25–50Deep dives: fast routing (9.1), live traffic (9.3), ETA (9.4)
50–60Rerouting or tiles, follow-ups, wrap-up

A 90-minute interview

0–8Frame, including privacy and poor connectivity
8–15Must do, how well, numbers
15–22Nouns, contract, data flow
22–35First working version
35–75Deep dives 9.1–9.6 and the final picture
75–85Follow-ups: offline, transit, a bad graph build
85–90Trade-offs, metrics, 10×
LevelWhat a strong answer shows
Mid-levelTiles through a CDN, a graph search for routes, a location stream feeding traffic, a navigation session over a persistent connection.
SeniorWhy Dijkstra is too slow with numbers, precomputed shortcuts or partitions, map matching and per-segment aggregation, ETA from historical plus live speeds, local navigation on the phone.
Staff+Fast re-customisation for live weights, privacy by design in the pipeline, versioned graph rollouts with offline replay, load-aware routing so recommendations don't create jams, ETA quality as a measured product metric.

Common mistakes:

13. Try it, check yourself, read more

Route search lab. A small city as a grid of streets; every block takes one minute unless it's in the red jam. Pick a search and watch how much of the city it explores before finding the fastest route. Then switch the jam on and see the route bend around it.

A 30 × 17 grid (510 junctions). On a real continent Dijkstra would explore millions of junctions; precomputed shortcuts explore hundreds to a few thousand, which is why production routers use them.

What makes continental routing fast enough to answer in milliseconds?

Preprocessing turns a search over millions of nodes into a climb up and down a hierarchy of shortcuts.

Two million location pings arrive every second. What do you do with them?

Routing needs a speed per segment, not individual points. Aggregate in the stream and keep no identifiable traces.

For a two-hour trip, which speed should the ETA use for a road you'll reach in 90 minutes?

Traffic will have changed by then; time-of-week history predicts it better.

How does navigation keep working in a tunnel?

The server advises (ETA, reroutes); the phone does the guiding.
ResourceWhy
Customizable Route Planning (Delling, Goldberg, Pajor, Werneck, 2011)Partitioned graphs with fast re-customisation for live traffic.
Contraction hierarchiesThe shortcut idea in a readable overview.
Hidden Markov Map Matching Through Noise and Sparseness (Newson and Krumm, 2009)The standard way to snap GPS points to roads.
Traffic prediction with advanced graph neural networks (Google DeepMind)How ETA models use history and road structure.
OSRM and ValhallaOpen-source routing engines you can run on real map data.
Vector tile specificationWhat a vector tile contains.