Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

System Design (High-Level Design)  Module 25 – Case studies: location, mobility and logistics

Design maps, routing and ETA

Design a maps service: requirements, estimates and a first design for map tiles, routes on a road graph and arrival times from live traffic.

  • Advanced
  • 30 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free intro, Pro: 5 of 30 minutes free
Free: About 174,000 tiles a second, and 400,000 probe points. With a pass: the other 16 sections and 3 interview answers, about 25 minutes.

What you will learn

  • Estimate tile traffic, edge bandwidth, tile storage and the probe stream for a national maps service
  • Publish vector map tiles through a CDN without emptying the edge caches on every map update
  • Compare Dijkstra, A* and contraction hierarchies by the work of a query, and apply live traffic without a rebuild
  • Estimate arrival times from probe speeds, usual speeds and corrections learned from finished trips
  • Convert addresses that rely on PIN codes, landmarks and DIGIPIN grid codes into points

Before you start

What you’ll learn · Before you start

What you will learn

  • Estimate tile traffic, edge bandwidth, tile storage and the probe stream for a national maps service
  • Publish vector map tiles through a CDN without emptying the edge caches on every map update
  • Compare Dijkstra, A* and contraction hierarchies by the work of a query, and apply live traffic without a rebuild
  • Estimate arrival times from probe speeds, usual speeds and corrections learned from finished trips
  • Convert addresses that rely on PIN codes, landmarks and DIGIPIN grid codes into points

Before you start

On this page

A national maps service answers about 174,000 tile requests a second at its peak and takes in 400,000 speed reports a second, yet a route across 50 million road segments must come back within 300 ms. To design maps for a country, you build three systems that share one map database.

Tiles draw the map: squares at every zoom level, built ahead of time and served from a CDN, so a phone downloads only the squares on its screen. Routing finds the fastest path through a graph of junctions and road segments, preprocessed once so that a query touches only a few hundred junctions. The ETA, the estimated time of arrival, adds up the route’s segments at the speeds phones report now and the speeds usual for the hour each is reached, then applies corrections learned from finished trips. Whoever has to design maps needs all three.

About 174,000 tiles a second, and 400,000 probe points

Settle the scope first, writing down each assumption:

  • Which journeys? Driving, two-wheelers and walking in one country of about 3 million km², turn by turn.
  • Who calls it? 60 million daily users, and partner services, such as ride matching, that ask for many arrival times at once.
  • How fresh? A jam or a closed road reaches routes within minutes, a new road the tiles within a day.
  • How fast? A tile within 100 ms from the edge (CDN): One of a content delivery network's servers, placed close to users. The user's connection ends at the edge, which answers from its cache or fetches the response from the origin. More in “The life of a web request, hop by hop” and a route within 300 ms, at the p99 (99th percentile): The latency within which 99 % of requests finish, so the slowest 1 % take longer. Tail latency is read from such high percentiles, because an average hides the slowest requests. More in “Latency, throughput and percentiles”.
  • How good? Most arrival times within 10 %, with no steady lean towards early or late.

So the service draws the map, geocodes, routes and predicts arrival times from live speed reports, and keeps serving its last good data when a pipeline fails. A common starting point is OpenStreetMap data, under the Open Database License: a product must credit OpenStreetMap and its contributors, and a database built from the data may be shared only under the same licence (OpenStreetMap). Its community tile servers may block heavy use and allow no offline use, so an app this size runs its own tile pipeline (OpenStreetMap Foundation).

Quantity Working Result
Tile requests, busiest hour 60 million × 5 map views × 20 tiles ÷ 86,400 s × 2.5 about 174,000 a second
Edge bandwidth at that peak 174,000 tiles × 25 KB × 8 bits about 35 Gbit/s
Vector tiles to zoom 14 3 million km² ÷ 5.3 km² a tile × 4/3 for the zooms above × 25 KB about 19 GB
Route requests, busiest hour 60 million × 0.4 ÷ 86,400 s × 2.5 about 690 a second
Probe points from navigating phones 2 million phones, one report every 5 s 400,000 a second
Road graph in memory 50 million segments, as many shortcuts, 40 bytes each about 4 GB a copy

Two facts shape the design. Tiles carry the most traffic but cache perfectly, because a tile is the same for everyone. The heavy writing is the probe stream: 400,000 reports a second become one speed per segment every minute.

Exercise · Easy · Python

Size tile traffic, edge bandwidth, the tile set and the probe stream for a maps service

Write four functions in sizing.py for the estimate sheet of a maps service. A day has 86,400 seconds, 1 KB is 1,000 bytes, 1 GB is 10⁹ bytes and 1 Gbit is 10⁹ bits.

  • tile_requests_per_second(daily_users, views_each, tiles_per_view, peak_factor): tile requests a second in the busiest hour, when that hour runs at peak_factor times the day's average rate.
  • edge_gbit_per_second(tiles_per_second, kb_per_tile): the bandwidth the edge servers send for that many tiles.
  • vector_tileset_gb(area_km2, tile_km2, kb_per_tile): the storage for a vector tile set of an area, where one tile at the deepest zoom covers tile_km2; every lower zoom together adds another third of that count.
  • probe_points_per_second(phones, seconds_between): speed reports a second from phones that each send one every seconds_between seconds.

The sample tests accept each figure within 10 %, as an estimate should.

Starter code · sizing.py

DAY_SECONDS = 86_400


def tile_requests_per_second(daily_users, views_each, tiles_per_view, peak_factor):
    """Tile requests a second in the busiest hour."""
    # Replace this line with your code.
    return 0


def edge_gbit_per_second(tiles_per_second, kb_per_tile):
    """Gbit/s the edge sends for that many tiles a second."""
    # Replace this line with your code.
    return 0


def vector_tileset_gb(area_km2, tile_km2, kb_per_tile):
    """GB for a vector tile set of the area, every zoom included."""
    # Replace this line with your code.
    return 0


def probe_points_per_second(phones, seconds_between):
    """Speed reports a second from navigating phones."""
    # Replace this line with your code.
    return 0
The sample tests · test_sizing.py
import math

from sizing import edge_gbit_per_second, probe_points_per_second, tile_requests_per_second, vector_tileset_gb


def near(actual, expected):
    """Within 10%, as an estimate should be."""
    return math.isclose(actual, expected, rel_tol=0.10)


def test_tiles_at_peak():
    """every view's tiles spread over the day, times the peak factor"""
    assert near(tile_requests_per_second(60_000_000, 5, 20, 2.5), 173_611)
    assert near(tile_requests_per_second(5_000_000, 3, 12, 3), 6_250)


def test_edge_bandwidth():
    """tiles times bytes, in gigabits"""
    assert near(edge_gbit_per_second(173_611, 25), 34.7)
    assert near(edge_gbit_per_second(6_250, 40), 2.0)


def test_tileset_storage():
    """the deepest zoom's tiles, a third more for the zooms above, times the bytes"""
    assert near(vector_tileset_gb(3_000_000, 5.29, 25), 18.9)
    assert near(vector_tileset_gb(50_000, 4.0, 30), 0.5)


def test_probe_stream():
    """one report per phone every few seconds"""
    assert near(probe_points_per_second(2_000_000, 5), 400_000)
    assert near(probe_points_per_second(300_000, 4), 75_000)
A hint

Tile requests: daily_users * views_each * tiles_per_view / 86_400 * peak_factor. Bandwidth multiplies tiles by bytes and by 8 for bits, then divides by 10**9. The tile set counts the deepest zoom's tiles (area_km2 / tile_km2), multiplies by 4/3 for the zooms above it, then by the bytes per tile.

The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Checkpoint

Check the estimate

  1. Question 1 of 2 At the peak the edge serves about 174,000 tiles a second, and a vector tile weighs about 25 KB. About how many Gbit/s leave the edge?

    Type a number.

    A hint

    Multiply tiles by bytes, then by 8 for bits; 1 Gbit is 10⁹ bits.

    Show the answer: Question 1 of 2

    Answer: 34.8 Gbit/s (anything from 31.3 to 38.3 counts)

    174,000 × 25,000 bytes = 4.35 × 10⁹ bytes a second, and × 8 = 34.8 × 10⁹ bits: about 35 Gbit/s, which is why the tiles must come from edge caches close to the phones, not from one origin.

  2. Question 2 of 2 2 million navigating phones each send one probe point every 5 seconds. How many points a second reach the traffic pipeline?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 400000 points a second (anything from 360000 to 440000 counts)

    2,000,000 ÷ 5 = 400,000 a second. That is the heavy write side of the design, while the far larger tile traffic is read-only and cached.

The first design: tiles, routes and speeds

Maps service: a CDN and tile storage, an API gateway with a geocoder, routing servers, a traffic pipeline and builders.Phone or browserAPI gatewayand geocoderTraffic pipelinespeed per segmentTile and graphbuildersCDN edgetiles by addressRouting serversroad graphin memoryTile storagevector tilesto zoom 14routes, ETAs,probe pointstilesprobe pointsroute, ETAnew speedsnew graphchanged tilesmiss

The first complete design of a maps service

Text description of the diagram

The diagram shows three paths.

  1. The phone or browser asks a CDN edge for map tiles by address; on a miss the edge fetches the tile from tile storage, which holds vector tiles up to zoom 14.
  2. Requests for routes and arrival times go to the API gateway, whose geocoder turns addresses into points, and on to the routing servers, which keep the road graph in memory.
  3. Navigating phones also send probe points through the gateway to the traffic pipeline, which computes a speed for each road segment and sends the new speeds to the routing servers.
  4. The tile and graph builders turn the map data into changed tiles for tile storage and a new road graph for the routing servers.

The phone takes tiles from the CDN, which fetches misses from tile storage. Route and arrival-time requests pass the API gateway, whose geocoder turns addresses into points, to routing servers holding the road graph in memory. Phones send probe points to the traffic pipeline, which publishes speeds every minute. Builders turn map edits into changed tiles and new graphs. Follow one phone through it:

Interactive · step by step One map view and one route through the first design Step through a phone that opens the map, asks for a route and navigates, and see which part answers each step.
One map view and one route through the first design, step 7 of 7. Showing Phone or browser, CDN edge (kept for the next phone), API gateway (address to a point), Tile storage, Routing servers (speeds of this minute), Traffic pipeline, Tile and graph builders. In focus: Tile and graph builders.tilesmissrequestsroute, ETAprobe pointsnew speedsPhone or browserCDN edgekept for the next phoneAPI gatewayaddress to a pointTile storagevector tiles to zoom 14Routing serversspeeds of this minuteTraffic pipelinespeed per segmentTile and graph builderschanged tiles

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. A map view. The phone opens the map and asks the CDN edge for the tiles on its screen, each by its address. A tile is the same for everyone, so most of them are already at the edge.
  2. A miss. One tile is not at this edge yet. The edge fetches it from tile storage, keeps a copy for the next phone, and answers.
  3. An address. The rider asks for a route to an address. The API gateway's geocoder turns the address into a point on the map.
  4. A route. A routing server finds the fastest path in the road graph it holds in memory, and adds up the arrival time from the speed of each segment.
  5. Probe points. While the phone navigates, it reports its position and speed every few seconds. The gateway passes the reports to the traffic pipeline.
  6. New speeds. Once a minute the traffic pipeline publishes a speed for every road segment that changed, and the routing servers use it for the next routes.
  7. Map edits. When the map data changes, builders turn the edits into changed tiles for tile storage and a new graph for the routing servers.

The questions this design must answer:

  • Raster or vector tiles? Raster tiles are images drawn on the server; Map tiles that carry shapes such as roads, rivers and labels as coordinates instead of an image, so the phone or browser draws and styles the map itself. carry shapes that the phone draws and styles itself.
  • Which search? Dijkstra explores outward from the start in order of travel time; A* steers it towards the target with a lower bound.
  • Contraction hierarchies: preprocessing adds shortcut edges, so a A road graph prepared once by adding shortcut edges in an order of importance, so that a route query searches from both ends only towards more important junctions. query only climbs from both ends towards more important roads.
  • Multi-level Dijkstra: times across nested cells of the graph are precomputed, so new speeds apply cell by cell.
  • ETA: probe speeds for the next few minutes, usual speeds for later segments, and corrections for waits at junctions.
  • Addresses: PIN codes, landmarks and India Post's open grid code that names a small square of the map; a geocoder uses it beside the PIN code, the locality and landmarks. grid codes turn an Indian address into a point.

Checkpoint

Check the first design

  1. Question 1 of 2 In the first design, where does the CDN edge get a tile it does not hold yet?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: From tile storage, which holds the vector tiles to zoom 14

    Phone, CDN edge, tile storage: tiles are built ahead of time and only fetched on a miss. Routes and arrival times take the other path, through the API gateway to the routing servers.

  2. Question 2 of 2 A jam starts on an arterial road. In the first design, how does it reach the next routes?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The phones' probe points reach the traffic pipeline, which publishes new segment speeds to the routing servers every minute

    Probe points go through the gateway to the traffic pipeline, which turns them into a speed per road segment each minute; the routing servers use those speeds for the next routes and arrival times.

Vector tiles stop at zoom 14 and cache better than raster tiles Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • New addresses only for changed tiles keep the edge warm through an update
  • Dijkstra settles every junction nearer than the target; A* steers towards it
  • A contraction hierarchy settles 75 junctions where Dijkstra settles 780
  • 400,000 probe points a second become one speed per segment each minute
  • Cell overlays take in new speeds; shortcuts must be rebuilt
  • Arrival times need history for later segments and corrections for waits
  • A PIN code narrows the search; a DIGIPIN names a 4 m square
  • What gives way at 10× and 100×
  • Failure drills: each path keeps serving its last good data
  • Alternatives considered and rejected
  • What each level is expected to cover
  • A sample answer and a 45-minute self-mock
  • Practise: the whole design, one question at a time
  • Interview questions
    • Your routing service answers routes in under a millisecond with contraction hierarchies built every night from usual speeds. Product now wants routes and arrival times to follow live traffic, with speeds changing every minute. What breaks, and how do you change the design?
    • In one city, evening arrival times are 5 to 10 minutes too optimistic on most trips, although the routes look right and the traffic layer shows the jams. How do you find the cause, and what do you change?
    • A new map build is published every night. For an hour after each release, tile latency doubles and the load on the tile origin rises tenfold. Explain why, and design a release that avoids it.
  • Key takeaways

4 diagrams · 6 runnable examples (Python) · 3 interview answers · about 68 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Read a complete sample first: Design ride hailing like Uber or Ola: matching

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.