"Design Google Maps" is one of the meatiest system design interview questions you can get. It bundles three distinct problems into one: serving a huge visual map, indexing the whole planet spatially, and computing the fastest route across a graph with hundreds of millions of edges. Interviewers love it because it forces you to make crisp scoping decisions instead of trying to boil the ocean.
Here is a complete google maps system design walkthrough with an architecture diagram, following the standard requirements → API → design → data → scale arc.
[ Mobile / Web Client ]
|
+------+------+
| |
v v
[ CDN ] [ API Gateway / LB ]
map tiles |
(blob store) +----------------------------------+
| | | |
v v v v
[ Tile svc ] [ Geocode/ [ Routing [ Traffic
Places svc] engine ] ingest ]
| | | |
v v v v
[ Blob + [ Geospatial [ Road graph [ GPS ping
quadtree ] index: S2/ + contraction stream ->
geohash DB] hierarchies] segment
+ ETA weights speeds ]
1. Clarify the requirements
Functional requirements
- Render the map for any location and zoom level (pan/zoom)
- Search for a place or address (geocoding)
- Return the fastest route between two points, with turn-by-turn directions and ETA
- Reflect live traffic in routes and ETAs
Non-functional requirements
- Low latency — tiles and routes in well under a second
- Very high availability and global reach
- Read-heavy: rendering and routing vastly outnumber map edits
- Freshness: traffic must feed into routing within minutes
Back-of-the-envelope scale: a global road network is on the order of hundreds of millions of nodes and edges. Tiles are the biggest data volume — the world pre-rendered across ~20 zoom levels is petabytes of static imagery. Since it is a design a mapping service problem, scope it down: focus on tiles, geospatial indexing, and routing, and mention that map data ingestion (satellite, Street View, edits) is a separate offline pipeline.
2. API design
Three read paths carry most traffic: fetch tiles, geocode a query, and compute a route.
GET /tiles/{z}/{x}/{y}.png
-> 200 pre-rendered map image for that quadtree cell
GET /geocode?q=1600+Amphitheatre+Pkwy
-> 200 { "lat": 37.4224, "lng": -122.0841, "placeId": "..." }
GET /route?from=lat,lng&to=lat,lng&mode=drive
-> 200 { "polyline": "...", "distanceM": 14200,
"etaSec": 1080, "steps": [ ... ] }
3. Map tiles and storage
You never ship the whole map to the client. Instead the map is pre-rendered into small square tiles (typically 256×256 px) at every zoom level, addressed by a quadtree: at zoom z the world is a 2z×2z grid, and each tile is identified by (z, x, y). Zooming in splits one tile into four children — that is the quadtree.
Tiles are static, immutable images, so they are the easy part: store them in blob storage (S3/GCS) and serve from a CDN. The client requests only the handful of tiles inside the current viewport, and the browser/app caches them. Vector tiles (drawing instructions rather than pixels) are a common refinement that lets the client re-style and rotate without re-fetching.
4. The road graph
Routing runs on a weighted directed graph. Intersections are nodes; road segments are edges. Each edge carries a weight — usually travel time, derived from length, speed limit, road class, turn restrictions, and live traffic. One-way streets and turn penalties are why the graph is directed.
This graph is enormous and mostly static, so it is built offline from raw map data and loaded into memory on the routing servers. The dynamic part is the weights, which traffic keeps updating.
5. Routing at scale
The naive answer is Dijkstra or A*. They are correct, but on a continent-scale graph a single query would explore millions of nodes — far too slow for interactive use. The real trick is precomputation.
Contraction hierarchies (CH) are the standard technique. In an offline phase you rank nodes by importance and "contract" them one by one, adding shortcut edges that preserve shortest-path distances. At query time a bidirectional search only ever moves "upward" through the hierarchy, touching a tiny fraction of the graph and returning routes in milliseconds. The trade-off: CH preprocessing is expensive and assumes fixed weights, which is awkward when traffic changes constantly.
Customizable route planning (CRP) addresses that by splitting preprocessing into a slow, rarely-run phase (partition the graph into cells) and a fast metric customization phase that recomputes only cell-boundary shortcuts when weights change. That is how live traffic can reshape routes without rebuilding everything.
Interview signal: saying "Dijkstra" alone is a red flag at scale. The strong answer is "model it as a weighted graph, then precompute — contraction hierarchies for static weights, CRP-style customization when traffic must update the weights cheaply."
6. Geospatial indexing
A geospatial index maps 2D coordinates onto a 1D sortable key so that points near each other in the world stay near each other in the key space. That single idea powers snap-to-road, "restaurants near me," and sharding the map by region. The common schemes:
| Scheme | Idea | Used by |
|---|---|---|
| Geohash | Interleave lat/lng bits into a base-32 string; shared prefix = nearby | Redis, Elasticsearch |
| Quadtree | Recursively split space into 4 cells; also how tiles are addressed | Tile pyramids, spatial DBs |
| S2 | Project the sphere onto a cube, use a Hilbert curve for cell IDs | Google (S2) |
| H3 | Hexagonal grid; uniform neighbor distances | Uber (H3) |
For a nearest-place query you compute the cell ID of the user, then scan that cell and its neighbors instead of the whole planet. To snap a GPS point to a road, you index road segments spatially and query the local cell for candidates.
7. ETA and traffic
ETA is not a separate system — it is the routing weight. The travel time of a route is the sum of the current time-weights on its segments. The interesting part is keeping those weights fresh:
- Live GPS pings from phones running the app are aggregated per road segment to estimate current speed.
- Historical patterns (time of day, day of week) fill gaps where live data is sparse.
- Updated segment speeds flow into the metric-customization step so routing reflects current conditions.
The traffic pipeline is a classic stream-processing job: ingest pings, map-match them to segments, aggregate, and publish updated weights.
Key trade-offs the interviewer probes
- Raster vs vector tiles. Raster is dead simple to serve but heavy and un-restylable; vector tiles are smaller and flexible but push rendering to the client.
- CH vs CRP. Contraction hierarchies give the fastest queries but hate weight changes; CRP trades a little query speed for cheap traffic updates.
- Precompute vs on-the-fly. More preprocessing means faster queries but slower/heavier updates — the recurring tension in every mapping design.
- Index choice. Geohash is simplest; S2/H3 handle sphere distortion and neighbor uniformity better at global scale.
Framework reminder: every system design answer follows the same arc — requirements → estimates → API → high-level design → data model → scale → trade-offs. Keep the system design cheat sheet in mind and narrate which stage you're in.
Structure any design answer with live AI support
CoPilot Interview surfaces a structured design skeleton — requirements, API, data model, and scaling — in about 4 seconds during real Zoom and Teams calls. Free for Windows and macOS, invisible on screen-share.
Download freeFAQ
How does Google Maps serve the map itself?
The map is pre-rendered into square image tiles at many zoom levels using a quadtree scheme. Tiles are static, so they are stored in blob storage and served from a CDN. The client only requests the handful of tiles visible in the current viewport.
How do you compute the fastest route at scale?
Model the road network as a weighted graph, then precompute shortcuts so queries are fast. Plain Dijkstra is too slow for continent-scale graphs, so production systems use contraction hierarchies or a similar precomputation that lets a query touch only a tiny fraction of the graph, returning routes in milliseconds.
What is geospatial indexing and why does it matter?
A geospatial index maps 2D coordinates to a 1D sortable key so nearby points cluster together. Geohash, Google's S2, Uber's H3, and quadtrees all do this. It powers snap-to-road, nearest-place lookups, and sharding the map by region.
How does Google Maps estimate ETA and use traffic?
Each road segment carries a travel-time weight. Live GPS pings from phones are aggregated to estimate current speed per segment, historical patterns fill gaps, and the routing engine sums segment times along the path. ETA is the routing weight, not a separate system.
How do you keep routing fresh as traffic changes?
Live conditions update segment weights continuously, but recomputing full contraction hierarchies is expensive. Systems use customizable route planning that separates a rarely-changing preprocessing phase from a cheap per-query metric update, so traffic changes apply without a full rebuild.