Design Google Maps & Distributed Routing Engine
1. Problem Statement & Scope Clarification
System Mission
Design a planetary-scale digital mapping, shortest-path navigation, and real-time dynamic traffic routing platform (similar to Google Maps, Apple Maps, and Waze). The platform must ingest billions of live GPS telemetry pings from active devices, continuously reconstruct planetary traffic congestion overlays via streaming analytics, serve zoomable vector map tiles with sub-20ms edge latency, and calculate optimal driving routes across hundreds of millions of road segments in under 25 milliseconds.
At a glance:
| Metric | Value |
|---|---|
| Scale | 1 Billion DAU |
| Active Telemetry | 4M Pings/sec |
| Graph | 100M Nodes, 300M Edges |
| Long-Distance Routing | < 25ms P99 |
| Tile Edge Hit Ratio | > 99.2% |
| In-Memory Graph RAM | ~9.6 GB |
| Tile Serving | CloudFront + S3 MVT |
| Telemetry Stream | Kinesis + Flink |
| Routing | Contraction Hierarchy |
Functional Requirements
- Hierarchical Vector Map Tile Rendering: Serve zoomable vector map tiles across zoom levels 0 through 21 using standard Web Mercator Slippy Map conventions ( coordinates) via Mapbox Vector Tile (MVT/PBF) format with sub-20ms edge latency.
- Shortest-Path Driving Directions (
GetDirections): Calculate optimal driving routes between origin and destination coordinates, accounting for complex turn restrictions, one-way streets, bridge weight limits, highway preferences, and dynamic real-time traffic speeds. - Accurate Estimated Time of Arrival (ETA): Continuously estimate arrival times by fusing historical segment velocity profiles, real-time telemetry speed observations, and traffic light delays.
- Dynamic Proactive Re-Routing: Monitor active in-flight navigation sessions and automatically push real-time detour recommendations via WebSockets/APNs when unexpected incidents, accidents, or gridlocks arise along the remaining route.
- Live GPS Map Matching (Viterbi HMM): Snap noisy mobile GPS coordinates ( error radius) to the most mathematically probable physical road network segments using Hidden Markov Models.
Non-Functional Requirements (SLAs & SLOs)
- Ultra-Low Latency:
- Map Tile Rendering (CloudFront CDN Edge): .
- Driving Route Calculation (Sub-continental): , .
- Real-Time Traffic Velocity Update Pipeline: Telemetry ping to live routing weight delta .
- Planetary Availability: uptime SLA for core navigation and directions APIs ( unscheduled downtime per calendar year).
- Scale: Support , concurrent navigation sessions, , and .
- Data Durability & Offline Support: Route polylines and turn-by-turn guidance steps cached locally on mobile devices; clients must navigate through tunnels and dead zones without connection drops via inertial dead reckoning.
Client GPU Vector Rendering: Map tiles are transferred as Protocol Buffer Mapbox Vector Tiles (.pbf) rather than prerendered raster PNGs. This reduces edge CDN egress bandwidth by over and enables the client device's GPU (Metal / Vulkan) to dynamically style traffic overlays, 3D building extrusions, and smooth rotational zoom with zero server re-baking.
2. Capacity & Scale Estimation (Back-of-the-Envelope Math)
Road Network Graph Sizing (Planetary Graph Memory)
The global drivable road network consists of intersections (vertices) and road segments (directed edges):
- Global Intersections (Vertices ): ().
- Global Directed Road Segments (Edges ): ().
- Compact In-Memory Forward-Star Graph Structs & Cache Line Alignment:
In standard object-oriented graphs (
std::vector<std::vector<Edge*>>), traversing adjacent edges triggers pointer chasing across disjoint heap allocations, generating continuous CPU L1/L2/L3 cache misses ( DRAM stall per miss). We pack the graph into a flat Forward-Star (Compressed Sparse Row) representation aligned to 64-byte CPU cache lines:- Vertex Struct (16 bytes):
lat(float32, 4B),lon(float32, 4B),first_edge_offset(uint32, 4B),ch_rank(uint32, 4B) . There is no storednode_id: after Hilbert renumbering (item 4) the node's id is its array index, which is what makes the layout compact. The CH rank has to live here because the query (Section 6.3) compares ranks on every edge relaxation. - Directed Edge Struct (16 bytes aligned):
target_node_id(uint32, 4B),distance_meters(uint32, 4B),base_traversal_time_ms(uint16, 2B),flags_and_turn_restrictions(uint16, 2B),live_speed_multiplier(uint8, 1B),road_class(uint8, 1B),padding(2B) = 16 bytes. - L1 Cache Line Density: Exactly occupy a single CPU cache line. When relaxing edges from vertex , a single memory bus fetch loads up to 4 contiguous candidate edges directly into L1 CPU cache.
- Spatial Locality via Hilbert Curve Renumbering: Intersections are renumbered along a 2D Hilbert Space-Filling Curve. Geographically adjacent intersections occupy adjacent indices in RAM, maximizing L2/L3 hardware prefetcher hit rates during graph traversal.
- Vertex Struct (16 bytes):
- Raw Graph Memory Footprint:
- Contraction Hierarchies (CH) Shortcuts Overhead ( shortcut edges):
- Crucial Architectural Conclusion: The entire planetary road graph fits comfortably inside the L3 cache / RAM of a single modern compute-optimized EC2 instance (
c6in.4xlargewith 32 GiB RAM and 50 Gbps network), completely eliminating distributed network RPCs during shortest-path graph search.
Telemetry Ingestion & Real-Time Traffic Volume
- Active In-Flight Drivers: streaming GPS telemetry.
- Broadcast Frequency: 1 ping every 5 seconds ().
- Global Telemetry Ingestion QPS:
- Telemetry Ingestion Bandwidth:
- Encoded binary Protobuf ping:
driver_id(16B),lat(8B),lon(8B),speed_mps(2B),bearing(2B),timestamp(8B),accuracy(2B) (with transport envelope ).
- Encoded binary Protobuf ping:
Map Tile Traffic & Edge CDN Caching
- Daily Tile Requests: ().
- Average Tile Request QPS:
- Average Vector Tile Size (MVT Protobuf): (compressed).
- Edge Cache Hit Ratio (Amazon CloudFront): .
- Origin S3 Tile Read QPS:
- CDN Peak Egress Bandwidth:
Directions & Routing Throughput
- Daily Completed Routes: .
- Average Routing QPS:
- Peak Routing QPS ( rush-hour spike + dynamic reroutes):
3. AWS-First High-Level Architecture
The platform is decoupled into three specialized subsystems: 1) Vector Map Tile Edge CDN, 2) Telemetry Ingestion & Stream Processing Pipeline, and 3) In-Memory Shortest-Path Routing & Rerouting Engine.
Synthesizing vector architecture diagram...
The platform is three subsystems that share only the edge. In the "Hierarchical Map Tile Subsystem" panel, a weekly batch job builds vector tiles from OpenStreetMap into S3, and CloudFront serves over 99% of tile requests from cache, so map display costs almost nothing at the origin. In the "GPS Telemetry & Live Traffic Pipeline" panel, about 4M GPS pings per second flow through the NLB and ingest fleet into Kinesis; Flink first snaps each noisy ping to the road it is really on (Viterbi map matching), then averages speeds per road segment over 5 minutes into Redis. In the "In-Memory Shortest-Path Routing Engine" panel, route requests hit servers holding the road graph in memory as contraction hierarchies, updated with live speeds every minute; active trips are stored in DynamoDB, and when a road on a trip closes, a Lambda pushes a detour to the driver. Precompute what is static (tiles, hierarchy), stream what changes (speeds), and combine them only at query time.
Data Flow Walkthrough
- Map Tile Discovery: When a user pans or zooms, the client computes required Mercator tile coordinates and queries CloudFront:
GET /v1/tiles/14/4823/6120.pbf. Over of requests hit CloudFront's distributed SSD edge caches (). Edge misses read directly from Amazon S3. The mobile device's Metal/Vulkan GPU shaders render vectors, 3D buildings, and labels locally. - Telemetry Ingestion: Active mobile devices emit binary GPS pings every 5 seconds to AWS NLB over persistent TCP/TLS connections. The ECS Ingestion fleet aggregates pings with the Kinesis Producer Library (many pings per Kinesis record) and writes to an Amazon Kinesis Data Stream of shards. Shard math: a shard accepts records/sec or , whichever binds first. Without aggregation, would need shards; with aggregation the byte limit binds instead, shards, provisioned as 500 for burst headroom.
- Map Matching via HMM: An Apache Flink application reads the raw GPS stream and executes a Viterbi Hidden Markov Model to eliminate GPS jitter () and snap points to directed physical road segments.
- Traffic Speed Calculation: Flink aggregates vehicle speeds across 5-minute tumbling windows per road segment, comparing observed velocities to posted speed limits. Speed overrides are published to an ElastiCache Redis Cluster.
- Route Calculation: When a rider requests directions (
POST /v1/navigation/routes), the API Gateway invokes the EC2 Routing Fleet. The routing engine runs an in-memory Bidirectional Contraction Hierarchy (CH) upward search across the global graph, incorporating dynamic live speed metrics from Redis. The optimal path, turn instructions, and polyline are returned in . - Dynamic Rerouting: If a severe traffic jam or bridge closure occurs, Flink emits a segment alert. The Reroute Trigger service scans active navigation sessions in DynamoDB whose remaining polyline traverses the blocked segment, recalculates alternative routes, and pushes proactive detour notifications to drivers.
Core Request Tracing Execution Walkthrough
| Step # | Event / Action | Component State | Distributed Transition | Output / Response |
|---|---|---|---|---|
| Step 1 | Driver mobile app emits batch GPS ping over TLS | Mobile telemetry background thread | NLB terminates TLS; forwards raw TCP to ECS task | Packet acknowledged with sub-millisecond ACK |
| Step 2 | ECS Ingestion task batches pings into Kinesis stream | Ephemeral buffer on ECS container | KPL-aggregated PutRecords batches into the ~500-shard Kinesis stream | Pings partitioned by PartitionKey = Hash(driver_id) |
| Step 3 | Apache Flink worker executes Viterbi HMM map-matching | Flink sliding state window (RocksDB) | Raw GPS sequence matched to physical directed road edge ID | Snapped edge emitted: (driver_101, seg_BayBridge_402) |
| Step 4 | Flink calculates 5-min harmonic mean speed per segment | Flink tumbling window aggregator | Compares observed to free-flow ; computes congestion ratio | Override written to ElastiCache: HSET speed:BayBridge 32kmh |
| Step 5 | User requests directions from SF to San Jose | Client navigation UI | API Gateway dispatches JSON payload to EC2 Routing Node | Request lands on c6in.4xlarge hosting in-memory CH graph |
| Step 6 | Routing engine runs Bidirectional Contraction Hierarchy query | In-memory Forward-Star Graph in RAM | Forward upward Dijkstra from SF meets Backward upward from SJ | Peak meeting node discovered in (exploring 1,200 nodes) |
| Step 7 | Unpack CH shortcuts into detailed geometry & turn steps | Routing Engine geometry unpacker | Recursive shortcut unpacking reconstructs full street polyline | Encoded polyline, step instructions, and ETA assembled |
| Step 8 | Persist active trip session in DynamoDB | Amazon DynamoDB | PutItem stores route polyline coordinates with 4-hour TTL | Session registered: SESSION#trip_sf_sj_9901 |
| Step 9 | Egress route response payload delivered to mobile client | API Gateway / Client SDK | JSON envelope with compressed encoded polyline | Client receives route, starts turn-by-turn guidance |
4. API Interface Design & Wire Protocols
1. Calculate Optimal Driving Route (POST /v1/navigation/routes)
Calculates optimal routes between origin and destination coordinates with dynamic traffic penalties.
Request Headers & Payload
httpPOST /v1/navigation/routes HTTP/1.1 Host: routes.navigation.platform.aws.internal Authorization: Bearer jwt_nav_usr_7718293041 Content-Type: application/json X-Correlation-ID: corr_nav_01J8N6K3P4V9QZ2W8M1Y7R4X
json{ "origin": { "latitude": 37.774929, "longitude": -122.419416 }, "destination": { "latitude": 37.338208, "longitude": -121.886329 }, "travel_mode": "DRIVING", "routing_preference": "FASTEST_WITH_TRAFFIC", "avoid_options": ["TOLLS", "FERRIES"], "departure_time_epoch_ms": 1767225600000, "alternatives_count": 2 }
Response: 200 OK
json{ "routes": [ { "route_id": "rt_fastest_sf_sanjose_101", "summary": "via US-101 S", "distance_meters": 77840, "duration_seconds": 3120, "typical_duration_seconds": 2700, "delay_seconds": 420, "congestion_level": "MODERATE", "encoded_polyline": "u{~nFjk`uVv]fYtXo\\rUqV...", "bounds": { "northeast": { "lat": 37.7751, "lon": -121.8859 }, "southwest": { "lat": 37.3380, "lon": -122.4201 } }, "legs": [ { "step_index": 0, "instruction": "Head southeast on Market St toward 10th St", "distance_meters": 450, "duration_seconds": 65, "maneuver": "DEPART" }, { "step_index": 1, "instruction": "Merge onto US-101 S via the ramp to San Jose", "distance_meters": 72400, "duration_seconds": 2850, "maneuver": "MERGE_HIGHWAY" } ] } ], "session_token": "sess_nav_88192a0e_sf_sj", "computation_latency_ms": 11.4 }
2. Fetch Mapbox Vector Tile (GET /v1/map/tiles/{z}/{x}/{y}.pbf)
Delivers a compressed binary protocol buffer containing vector geometry for Slippy Map coordinate .
httpGET /v1/map/tiles/14/2624/6332.pbf HTTP/1.1 Host: tiles.platform.aws.internal If-None-Match: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" Accept-Encoding: gzip, br
- Status:
200 OK(or304 Not Modified) Content-Type: application/x-protobufContent-Encoding: gzipCache-Control: public, max-age=604800, immutable(7-day edge cache)
3. High-Frequency Telemetry Ingestion Ping (Protobuf over UDP/TCP)
protobufsyntax = "proto3"; package navigation.telemetry; message GpsPingBatch { string device_id = 1; int64 batch_timestamp_ms = 2; repeated GpsPing pings = 3; } message GpsPing { double latitude = 1; double longitude = 2; float speed_mps = 3; float bearing_degrees = 4; int64 timestamp_epoch_ms = 5; float horizontal_accuracy_meters = 6; bool is_navigating = 7; }
5. Data Models & Storage Architecture
Database Selection Justification
- In-Memory Forward-Star Graph (EC2 RAM): Static and shortcut edge graphs are loaded directly into bare-metal memory structures. Pointer-based adjacency lists in C++ or Rust eliminate serialization overhead and enable memory lookups in nanoseconds.
- Amazon ElastiCache Redis 7 Cluster: Stores ephemeral, rolling 5-minute dynamic speed overrides for each directed road segment (
speed:edge:<edge_id>). - Amazon S3 Standard + CloudFront: Serves pre-rendered vector map tiles (
.pbf). S3 offers (11 9s) durability and near-infinite horizontal GET concurrency. - Amazon DynamoDB: Maintains active navigation session states, polyline coordinates, and driver route tracking coordinates for dynamic rerouting.
1. In-Memory Graph Memory Layout (Forward-Star Format)
text================================================================================ FORWARD-STAR COMPACT ROAD GRAPH IN RAM ================================================================================ Node Array (Length |V| = 100M): Index (NodeID) | Latitude (4B) | Longitude (4B) | First Edge Offset (4B) | Node Rank (4B) -------------------------------------------------------------------------------- 0 | 37.77492 | -122.41941 | 0 | 1204 1 | 37.77510 | -122.41890 | 4 | 8940210 ... | ... | ... | ... | ... Edge Array (Length |E| + |Shortcuts| = 405M): Edge Index | Target NodeID | Length (m) | FreeFlow Speed (km/h) | Flags / Restrictions -------------------------------------------------------------------------------- 0 | 1 | 120 | 45 | ONE_WAY_FORWARD 1 | 4 | 85 | 30 | NO_LEFT_TURN 2 | 902 | 240 | 50 | TOLL_ROAD 3 | 18 | 410 | 100 | CH_SHORTCUT_EDGE ================================================================================
2. S3 Vector Tile Directory Structure
Pre-compiled Mapbox Vector Tiles are stored hierarchically following Web Mercator Quadkeys:
texts3://planetary-map-tiles-production/ v2026_09/ streets/ 0/0/0.pbf # Global Zoom Level 0 1/0/0.pbf, 1/1/0.pbf # Zoom Level 1 ... 14/2624/6332.pbf # Zoom Level 14 (Street-level resolution) 21/1048576/894012.pbf # Zoom Level 21 (Building footprint resolution)
3. Active Navigation Session Table (Amazon DynamoDB)
- Table Name:
ActiveNavigationSessions - Billing Mode: On-Demand with auto-scaling
Partition Key (PK) | Sort Key (SK) | Attributes | Description |
|---|---|---|---|
SESSION#<session_id> | METADATA | driver_id, status="ACTIVE", destination_lat, destination_lon, eta_epoch_ms, ttl=1767232800 | Session header & target coordinates |
SESSION#<session_id> | ROUTE | encoded_polyline, edge_ids=[101, 102, 405, ...], total_distance_m=77840 | Active route road segment sequence |
EDGE#<edge_id> | SESSION#<session_id> | driver_id, expected_traversal_epoch_ms | Inverted index for lightning-fast detour fanout |
Unlock Complete Architecture & Production Runbooks
You have explored the free architectural preview (~37%). Spend 1 Coin to unlock the remaining 6 production deep-dive sections for a full 24 hours.