← Back to all questions
StaffGeospatialStreaming

Design a Real-Time Driver Location Tracking System

A full Staff-level walkthrough of a real-time driver-location pipeline that ingests 1.25M GPS updates/sec from 8M+ drivers, indexes them in an H3 hexagonal grid, and fans out to ride matching, live maps, and analytics — each on its own freshness tier. It trades query latency against geo-data locality, isolates ingestion from indexing from analytics so each fails independently, and treats mobile battery life as a first-class system constraint. Follow it top to bottom, or jump to any step.

Level
Staff
Category
Geospatial · Streaming
Interview time
60 min
100% free · No login required
WHAT THIS QUESTION TESTS
·H3 hexagonal indexing for spatial partitioning and nearby queries
·Ingesting 1.25M GPS updates/sec via a stateless gateway and Kafka
·Serving nearby-driver lookups at p99 < 100ms from an in-memory index
·Recovering the spatial index after node loss without dropping updates
★ STAFF-LEVEL SIGNALS
Geo-partitions Kafka by H3 cell, not driver_id, to match read locality and avoid hot partitions
Tiers freshness per consumer (sub-50ms matching vs 3s map vs minutes analytics) to cut cost 3-4x
Treats mobile battery life as a first-class constraint shaping the entire ingestion design
Isolates failure domains so ingestion, indexing, and analytics each fail independently
0

Scope & ambiguity

Framing statement:

“Before I dive in, let me frame how I’d approach this. Real-time driver location tracking is the backbone of Uber’s marketplace — it feeds ride matching (DISCO), ETA prediction (DeepETA), the live map riders see, surge pricing, and city-level analytics. This cuts across multiple teams: a location ingestion team, a spatial indexing team, the mobile platform team, the marketplace/matching team, and an analytics/ML team. I’d like to focus on the most architecturally interesting challenge: the real-time GPS ingestion pipeline at 1.25M updates/sec — specifically, how we ingest, process, index, and fan out driver locations to multiple consumers with sub-second latency at global scale. I’ll propose a phased approach.”

Phased delivery:

Phase
Timeline
Scope
Phase 1
0-3 months
Core GPS ingestion pipeline, in-memory H3 spatial index, gRPC gateway, Kafka streaming, single-region (US), serving ride matching and live map
Phase 2
3-9 months
Multi-region deployment (EMEA, APAC, LATAM), map matching and location smoothing, battery-efficient mobile SDK, historical analytics pipeline
Phase 3
9-18 months
Predictive location (where will driver be in 5 min), indoor positioning (airports/malls), V2X telemetry from connected vehicles, location platform as a service for internal teams

Team ownership:

Team
Ownership
Location Ingestion Team
GPS gateway, validation, Kafka pipeline, location writes
Spatial Indexing Team
H3-based in-memory index, Ringpop sharding, geo-queries for nearby drivers
Mobile Platform Team
Driver-side GPS SDK, battery optimization, adaptive frequency, offline buffering
Marketplace Team (DISCO)
Consumes location data for ride matching, supply positioning
Maps & Location Intelligence Team
Map matching, Kalman filtering, road-snapping, location smoothing
Analytics & ML Platform Team
Historical pipeline, ETA model training, supply forecasting, heat maps

Key ambiguity I’d challenge:

“When we say ’real-time,’ I want to clarify the latency budget for each consumer. Ride matching (DISCO) needs the freshest location within ~1 second. The rider-facing live map can tolerate 2-3 seconds with client-side interpolation. Analytics can tolerate minutes. This tiering affects whether we serve from the in-memory index, from Kafka directly, or from batch storage — and it significantly changes the cost model.”
1

Requirements

Functional Requirements (Phase 1)

  • FR1: Ingest GPS location updates from 8M+ active drivers globally at 4-second intervals (~1.25M updates/sec at steady state)
  • FR2: Maintain a real-time spatial index of all active drivers, queryable by geographic region (H3 cell, radius, bounding box)
  • FR3: Serve nearby-driver queries for ride matching (DISCO) with p99 < 100ms including geo-filtering
  • FR4: Stream driver locations to the rider-facing live map with < 3 second end-to-end latency
  • FR5: Persist location history for analytics, ETA model training, and regulatory compliance
  • FR6: Detect and filter anomalous GPS data (spoofing, GPS drift, impossible speed)

Non-Functional Requirements

Requirement
Target
Ingestion throughput
1.25M GPS updates/sec steady state, 2M+ peak (rush hours, events)
Ingestion latency (gateway to index)
p50 < 200ms, p99 < 500ms
Nearby-driver query latency
p50 < 20ms, p99 < 100ms
Live map update latency (end-to-end)
p50 < 1.5s, p99 < 3s
Availability
99.99% for ingestion path, 99.95% for analytics path
Data durability
99.999% for raw GPS data (regulatory requirement in some markets)
Horizontal scalability
Linear scaling with driver count across 10K+ cities

Organizational Context

  • Existing system: Uber already runs a location tracking system built on Ringpop (consistent hashing) and Go microservices — this is an evolution, not greenfield
  • Multi-tenant consumers: Location data is consumed by 10+ internal services (DISCO, DeepETA, live map, surge, safety, compliance, analytics), each with different latency/freshness requirements
  • Regulatory: GDPR (EU driver data residency), CCPA (California), local regulations requiring location data retention or deletion by jurisdiction
  • Mobile constraints: Driver phones range from high-end to low-end Android devices on 2G/3G/4G/5G networks across 70+ countries

Out of Scope (Explicitly)

  • Rider location tracking (different update frequency and privacy model)
  • The ride matching algorithm itself (DISCO) — we provide the location data it consumes
  • Map tile rendering and map display infrastructure
  • Driver authentication and identity verification
2

Back-of-envelope estimation

Scale Numbers

Metric
Value
Active drivers globally
8M+
Cities served
10,000+
GPS update frequency
Every 4 seconds (on trip), every 30 seconds (idle)
Steady-state updates/sec
~1.25M (5M on-trip drivers / 4s)
Peak updates/sec
~2M (rush hour, 1.6x multiplier)
Nearby-driver queries/sec
~500K (from DISCO, live map, surge)
Concurrent WebSocket connections (rider live map)
~2M at peak

Storage Estimation

Data
Calculation
Result
Single GPS update
{driver_id, lat, lng, heading, speed, timestamp, accuracy, trip_id, H3_cell} ~100 bytes
100B
Raw GPS per day
1.25M updates/sec x 86,400 sec x 100B
~10.8 TB/day
Raw GPS per month
10.8 TB x 30
~324 TB/month
In-memory spatial index
8M drivers x 120 bytes (location + metadata)
~960 MB
Kafka buffer (72-hour retention)
10.8 TB x 3 days
~32.4 TB
Historical (90-day raw retention)
10.8 TB x 90
~972 TB

Cost Estimation

Resource
Calculation
Monthly Cost
Kafka cluster (multi-region)
32 TB buffer, 1.25M msg/sec, 100+ brokers
~$250K
In-memory index servers
50 servers (Ringpop ring, 16 GB RAM each)
~$35K
gRPC gateway fleet
200 servers handling 1.25M conn/sec
~$75K
HDFS/S3 storage (tiered)
972 TB raw + aggregated warm/cold
~$120K
Cassandra (recent lookups)
32 TB hot, high write throughput
~$80K
Network/bandwidth
~50 Gbps sustained cross-region
~$200K
Total
~$760K/month

Architectural implication: The dominant costs are Kafka (high-throughput streaming) and storage (10 TB/day adds up fast). We need aggressive data tiering: hot data (last 24h) in Cassandra for real-time lookups, warm (7-90 days) in HDFS for analytics, cold (90+ days) aggregated and archived in S3. The in-memory index is surprisingly cheap — 8M drivers fit in under 1 GB — so we can afford redundant copies across regions.

3

API design

External API (Mobile SDK → Backend)

# GPS Update Ingestion (gRPC — driver mobile SDK)
rpc SendLocationUpdate(LocationUpdateRequest) returns (LocationUpdateResponse)
LocationUpdateRequest { driver_id: string, locations: repeated LocationPoint }
LocationPoint { latitude: double, longitude: double, heading: float,
speed: float, accuracy: float, timestamp: int64, source: enum {GPS, NETWORK, FUSED} }
 
# Nearby Driver Query (internal gRPC — used by DISCO, live map)
rpc GetNearbyDrivers(NearbyDriversRequest) returns (NearbyDriversResponse)
NearbyDriversRequest { latitude: double, longitude: double, radius_meters: int32,
max_results: int32, filters: { vehicle_type: [], status: enum, min_rating: float } }
 
# Driver Location Stream (WebSocket — rider live map)
WSS /api/v1/trips/{trip_id}/driver-location
Server pushes: { lat, lng, heading, speed, eta_seconds, timestamp } every 2s
 
# Historical Location (REST — analytics, compliance)
GET /api/v1/drivers/{driver_id}/location-history?start={ts}&end={ts}&resolution={raw|1min|5min}
GET /api/v1/regions/{h3_cell}/driver-density?timestamp={ts}&resolution={h3_level}

Inter-Service Contracts

SERVICE: LocationGateway
OWNER: Location Ingestion Team
PROTOCOL: gRPC (from mobile SDK), publishes to Kafka
 
RPC SendLocationUpdate(LocationUpdateRequest) returns (LocationUpdateResponse)
- Latency SLA: p99 < 50ms (ack to device)
- Availability SLA: 99.99%
- Auth: JWT token validation, device fingerprint
- Validation: speed < 200 km/h, accuracy < 100m, timestamp within 60s of server time
 
EVENTS PUBLISHED:
Topic: location.driver.updates
Schema: DriverLocationEvent (Protobuf)
Events: LOCATION_UPDATED, DRIVER_ONLINE, DRIVER_OFFLINE
Partition key: H3_cell_id (resolution 4) — co-locates geographically nearby drivers
Retention: 72 hours
Throughput: 1.25M events/sec
SERVICE: SpatialIndexService
OWNER: Spatial Indexing Team
PROTOCOL: gRPC
 
RPC GetNearbyDrivers(NearbyDriversRequest) returns (NearbyDriversResponse)
- Latency SLA: p99 < 50ms
- Availability SLA: 99.99%
- Consistency: Eventual (location may be up to 4 seconds stale)
 
RPC GetDriverLocation(DriverLocationRequest) returns (DriverLocationResponse)
- Latency SLA: p99 < 10ms
- Used by: live map, ETA service
SERVICE: LocationAnalyticsPipeline
OWNER: Analytics & ML Platform Team
PROTOCOL: Kafka consumer → Apache Flink → HDFS/S3; gRPC for on-demand queries
- Consumer group: analytics-pipeline
- Query SLA: p99 < 500ms, 99.95% availability

API Governance

  • Versioning: Protobuf field numbering for backward compatibility on gRPC; URI versioning for REST endpoints
  • Schema registry: Confluent Schema Registry for Kafka topics; Protobuf for all inter-service contracts
  • Rate limiting: Per-driver: max 1 update/sec (SDK enforces 4s interval, gateway rejects faster); Per-consumer: DISCO gets 500K queries/sec quota, live map gets 200K/sec
  • Backpressure: If Kafka consumer lag exceeds 30 seconds, alert; if gateway queue depth exceeds 10K, start shedding idle-driver updates (preserve on-trip updates)
4

Data model

Core Entities

Entity: DriverLocation (hot — in-memory spatial index)
- driver_id: UUID (PK)
- latitude: DOUBLE
- longitude: DOUBLE
- h3_cell_id: STRING (H3 resolution 9, ~0.1 km² hex)
- heading: FLOAT (degrees)
- speed: FLOAT (m/s)
- accuracy: FLOAT (meters)
- timestamp: TIMESTAMP (device time)
- server_timestamp: TIMESTAMP
- status: ENUM {AVAILABLE, ON_TRIP, IDLE, OFFLINE}
- vehicle_type: STRING
- trip_id: UUID (nullable)
- city_id: INT
 
Entity: RawLocationEvent (Kafka + Cassandra hot store)
- event_id: UUID (PK), driver_id: UUID (partition key)
- latitude/longitude: DOUBLE, heading: FLOAT, speed: FLOAT, accuracy: FLOAT
- device_timestamp: TIMESTAMP, server_timestamp: TIMESTAMP (clustering key, DESC)
- h3_cell_id: STRING, trip_id: UUID (nullable), source: ENUM {GPS, NETWORK, FUSED}
 
Entity: ProcessedLocationEvent (after map matching + smoothing)
- event_id: UUID (PK), driver_id: UUID
- snapped_latitude/longitude: DOUBLE (road-snapped)
- road_segment_id: STRING (OpenLR reference), confidence: FLOAT
- interpolated: BOOLEAN, timestamp: TIMESTAMP
 
Entity: DriverLocationAggregate (warm — HDFS/Hive)
- driver_id: UUID, date: DATE (partition key), city_id: INT
- h3_cell_id: STRING (resolution 7), time_bucket: TIMESTAMP (5-min buckets)
- avg_speed: FLOAT, distance_km: FLOAT, update_count: INT

Data Ownership Boundaries

Data
Owner Service
Access Pattern for Others
Real-time driver location (in-memory)
SpatialIndexService
Sync gRPC query (p99 < 50ms)
Raw location events (stream)
LocationGateway
Kafka topic subscription (location.driver.updates)
Raw location events (stored)
LocationAnalyticsPipeline
Cassandra for recent (< 24h), HDFS for older
Processed/snapped locations
MapsLocationIntelligence
gRPC query or Kafka topic (location.driver.snapped)
Location aggregates
LocationAnalyticsPipeline
Hive/Presto SQL queries
Driver metadata (vehicle type, status)
DriverService (external)
Sync gRPC (cached 30s in spatial index)

Storage Technology Choices

Data
Technology
Rationale
Alternative Considered
Real-time spatial index
Custom in-memory (Go) + Ringpop
Sub-ms geo-queries, ~1 GB total, Ringpop provides consistent hashing for sharding
Redis GeoSet (rejected: extra network hop, less control over H3 indexing)
Event streaming
Apache Kafka
1.25M msg/sec proven at Uber scale, H3-partitioned topics, multi-consumer
Apache Pulsar (rejected: Uber's Kafka expertise and tooling investment)
Hot location store (< 24h)
Apache Cassandra
High write throughput (1.25M/sec), time-series access pattern, tunable consistency
ScyllaDB (rejected: smaller operational experience at Uber)
Warm/historical (7-90 days)
HDFS + Apache Hive
Cost-effective bulk storage, Uber's existing data lake, Presto queries
S3 + Athena (rejected: Uber runs on-prem HDFS clusters)
Cold archive (90+ days)
S3 / Google Cloud Storage
Cheapest per-GB, lifecycle policies, regulatory retention
HDFS cold tier (rejected: higher cost for rarely-accessed data)
Map matching cache
Redis
Road segment lookups need sub-ms latency, ~50 GB for road network graph
In-process cache (rejected: too large, better shared across instances)

Data Lifecycle

HOT (0-24 hours): In-memory spatial index (latest per driver) + Cassandra (all events)
Full resolution, sub-second query latency
WARM (1-90 days): HDFS/Hive, raw events + 5-min aggregates
Queryable via Presto, used for ML training and analytics
COLD (90+ days): S3 with Parquet format, aggregated to 1-hour buckets
Anonymized (driver_id → anonymous_id), regulatory retention
DELETE (per GDPR): Raw data deleted after retention period; aggregated/anonymized data retained indefinitely
5

High-level architecture

Architecture Diagram

[Driver Mobile App - GPS SDK]
(Adaptive frequency: 4s on-trip, 30s idle)
|
gRPC (batched)
|
[Global Load Balancer]
(GeoDNS → nearest region)
|
+---------------+---------------+
| | |
[US Region] [EU Region] [APAC Region]
| | |
[Location Gateway] [Location Gateway] [Location Gateway]
(gRPC, validation, (gRPC, validation, (gRPC, validation,
rate limiting) rate limiting) rate limiting)
| | |
+-------+-------+-------+-------+
| |
[Kafka Cluster - location.driver.updates]
(Partitioned by H3 cell resolution 4)
(Cross-region replication via uReplicator)
|
+------------+------------+------------+
| | | |
[Spatial Index [Map Match [Analytics [Trip Location
Service] Service] Pipeline] Streamer]
(Ringpop ring, (Kalman + (Flink → (WebSocket →
in-memory H3 HMM snap HDFS/S3) rider app)
index) to roads)
| | |
[gRPC API] [Kafka: location. [Cassandra [Rider Live Map
driver.snapped] hot store] WebSocket GW]
| |
Consumers: [HDFS / Hive / S3]
- DISCO (ride matching) (Historical analytics,
- Surge Pricing ML training data)
- DeepETA
- Safety Platform
- City Operations Dashboard

Service Boundaries with Ownership

Service
Team
Data Store
Scaling Strategy
Consistency
SLA
Location Gateway
Location Ingestion
Stateless (writes to Kafka)
Horizontal, per-region, auto-scale on CPU
p99 < 50ms ack, 99.99%
Kafka Cluster
Infrastructure/SRE
Disk (72h retention)
Partition-level scaling, H3-based partitions
At-least-once delivery
99.99% uptime, < 100ms publish
Spatial Index Service
Spatial Indexing
In-memory (Ringpop ring)
Consistent hash ring, add nodes to scale
Eventual (4s staleness budget)
p99 < 50ms query, 99.99%
Map Match Service
Maps & Location Intelligence
Redis (road network cache)
Horizontal, stateless compute
p99 < 100ms, 99.95%
Trip Location Streamer
Location Ingestion
Stateless (reads Kafka, pushes WS)
Horizontal, scale on connection count
p99 < 3s end-to-end, 99.95%
Analytics Pipeline
Analytics & ML Platform
HDFS / Cassandra / S3
Flink parallelism, batch job scaling
Eventual (minutes acceptable)
99.9%, data completeness > 99.5%

Sync vs Async Communication

Communication
Type
Rationale
Driver SDK → Location Gateway
Sync (gRPC)
Driver needs ack to confirm delivery, retry on failure
Location Gateway → Kafka
Async (produce)
Decouple ingestion from all downstream consumers
Kafka → Spatial Index Service
Async (consume)
Index updated continuously but consumer manages own pace
DISCO → Spatial Index Service
Sync (gRPC)
Ride matching needs immediate nearby-driver response
Kafka → Map Match Service
Async (consume)
Map matching can lag raw updates by seconds
Kafka → Analytics Pipeline
Async (consume + batch)
Analytics tolerates minutes of lag
Trip Location Streamer → Rider App
Sync (WebSocket push)
Rider expects real-time driver movement

Failure Domain Boundaries

DOMAIN 1: Ingestion (Gateway → Kafka)
Impact: Stale spatial index. Mitigation: SDK buffers 5 min, multi-region failover, RF=3.
 
DOMAIN 2: Spatial Index (Ringpop)
Impact: DISCO can't find nearby drivers. Mitigation: SWIM auto-heals in <5s, replica ring,
fallback to Cassandra recent-locations with degraded latency.
 
DOMAIN 3: Map matching pipeline
Impact: Jittery raw GPS on rider map. Mitigation: client-side interpolation, serve raw if
snapped unavailable. No functional impact.
 
DOMAIN 4: Analytics (Flink → HDFS)
Impact: Delayed historical data. Mitigation: Kafka 72h retention, pipeline catches up.
Zero user-facing impact.
6

Deep dives

WHERE STAFF IS WON

Deep Dive 1: GPS Update Pipeline at 1.25M Updates/Sec

This is the core engineering challenge. Let me walk through the entire path of a GPS update.

Scale context:

Scale: 8M+ active drivers, ~5M on-trip at peak, GPS update every 4 seconds
= 1.25M updates/sec steady state, 2M+ at peak (rush hours)
Total daily volume: 1.25M × 86,400 = 108 billion events/day

End-to-end pipeline:

[Driver Phone GPS] → [Mobile SDK] → [Location Gateway (gRPC)]
→ [Kafka (partitioned by H3 cell)]
→ [Spatial Index Service (updates in-memory H3 index)]
→ [Map Match Service (road-snaps location)]
→ [Analytics Pipeline (historical storage)]
→ [Trip Location Streamer (pushes to rider app)]

Location Gateway (gRPC ingestion):

1. Accept GPS updates: {driver_id, lat, lng, heading, speed, timestamp, accuracy}
2. Validate: speed < 200 km/h, accuracy < 100m, timestamp within 60s of server time,
anti-spoofing via cell-tower triangulation
3. Enrich: compute H3 cell (res 9), attach server_timestamp, lookup driver status from cache
4. Publish to Kafka: location.driver.updates, partition key = H3 cell (res 4)
→ co-locates geographically nearby drivers on same partition
5. Batch handling: SDK buffers on poor network, gateway deduplicates by (driver_id, timestamp)
 
Fleet: 200 stateless servers, ~6,250 updates/sec each, auto-scale on CPU

Kafka topic design:

Topic: location.driver.updates
256 partitions (H3 res-4 cells), RF=3, 72h retention, ~100B/msg Protobuf
Throughput: 1.25M msg/sec = ~125 MB/sec
5+ consumer groups: spatial index, map match, analytics, trip streamer, safety
 
Why H3-partitioned (not driver_id): DISCO queries by geography, not by driver.
H3 partitioning gives spatial locality and avoids hot-spots (dense cities naturally
have more cells, spreading load evenly).

In-memory spatial index (Ringpop):

50-node consistent hash ring. Each node owns H3 res-4 cells, stores
H3_cell_res9 → [{driver_id, lat, lng, heading, speed, ts}].
Total: ~8M drivers × 120B = ~960 MB. Each node: ~160K drivers.
 
Update: Kafka consumer → hash H3_cell → owning Ringpop node → update in-memory.
Query: (lat, lng, radius) → H3 k-ring → fan out to owning nodes → filter → merge top-N.
 
Performance: point lookup < 1ms, nearby (500m, ~7 cells) p50 < 10ms, p99 < 50ms.
Ring rebalance on failure: < 5s (SWIM protocol).

Deep Dive 2: Location Smoothing and Map Matching

Problem: Raw GPS is noisy — especially in urban canyons (Manhattan, Hong Kong), tunnels, parking garages. A driver on 5th Avenue might appear to be on 6th Avenue due to GPS multipath reflection off buildings.

Processing pipeline (per GPS update):

[Raw GPS Point] → [Outlier Detection] → [Kalman Filter] → [Map Matching (HMM)]
→ [Interpolation]
→ [Dead Reckoning]
 
1. Outlier Detection: reject if speed > 200 km/h between points, accuracy > 100m, altitude
delta > 50m (GPS altitude is very noisy)
 
2. Kalman Filter: state vector [lat, lng, v_north, v_east], GPS accuracy as measurement noise,
constant-velocity process model. Outputs smoothed position every 4s GPS fix.
 
3. Map Matching (HMM + Viterbi):
- States: road segments within 50m of GPS point
- Emission: Gaussian distance from GPS to road segment
- Transition: route distance vs. great-circle distance between consecutive segments
- Viterbi finds most probable road segment sequence
- Confidence < 0.6 → fall back to raw GPS (off-road, parking lot)
- Uses Uber road network graph with OpenLR references
 
4. Interpolation: between 4s GPS fixes, linear interpolation along matched road segment
at estimated speed, accounting for road curvature → smooth driver icon on rider map
 
5. Dead Reckoning (tunnels, underground): advance along road at last known speed for up
to 60s. After 60s: "Location unavailable." On GPS re-acquisition: snap and reconcile.

Map matching at scale: Road network graph in Redis (~50 GB global). Per-update: query nearby road segments, maintain HMM state per-driver in memory (last 5 segments). Warm-up: ~3 GPS fixes to converge. Heavy markets (NYC, London, São Paulo): pre-warmed segment caches.

Deep Dive 3: Battery-Efficient Mobile SDK

Challenge: Continuous GPS tracking on 8M driver devices drains batteries, which is an existential threat — a driver with a dead phone cannot accept rides.

Adaptive location strategy:

Mode | GPS Frequency | Network Batch | Accuracy Target | Power Draw
-----------------+---------------+---------------+-----------------+-----------
On-Trip | 4 seconds | 5 points/req | < 10m | High
Available (idle) | 30 seconds | 10 points/req | < 50m | Medium
Idle (> 10 min) | 60 seconds | 15 points/req | < 100m | Low
Offline | None | None | N/A | None
 
Transitions:
- Trip assigned → On-Trip mode (server push via FCM/APNs)
- Trip completed + 2 min idle → Available mode
- No activity 10 min → Idle mode
- Driver taps "Go Offline" → Offline mode (stop tracking entirely)

Battery optimization techniques:

1. Fused Location Provider: combine GPS + WiFi + cell tower + accelerometer
- On-Trip: high accuracy (GPS dominant); Available: balanced (WiFi/cell sufficient)
 
2. Batched network calls: buffer 5-15 GPS points, send in single gRPC request
- Radio wake-up is the dominant battery cost, not GPS itself
- On poor network (2G/3G): increase batch size to 20-30 points
 
3. Motion detection: accelerometer detects stationary phone → reduce GPS to 60s
- Resume normal frequency on movement detected
 
4. Background execution: iOS significant-change service as fallback; Android foreground
service with persistent notification; geofence triggers for high-demand areas
 
5. Measured impact: 15% battery/hr unoptimized → 3-5%/hr on-trip, ~1%/hr available
- Target: driver completes 8-hour shift without charging

Deep Dive 4: Historical Analytics Pipeline

Purpose: Every GPS update ever recorded feeds ML models (DeepETA, surge forecasting), city operations (heat maps, traffic patterns), and regulatory compliance.

Pipeline architecture:

[Kafka: location.driver.updates] → [Apache Flink]
├→ Real-time aggregates (5-min heat maps, supply density) → Redis/Druid (dashboards, surge)
├→ Raw event write → Cassandra (<24h) → HDFS/Hive (1-90d) → S3 (>90d)
└→ Derived events (trip trajectories, speed profiles) → ML Feature Store (DeepETA, supply)

Data volumes and retention:

Raw: ~10.8 TB/day. Hot (< 24h): Cassandra. Warm (1-90d): HDFS Parquet partitioned by
(date, city_id, h3_res4). Cold (90d+): S3 Parquet, 5-min aggregates, anonymized.
GDPR: delete raw per driver on request, retain aggregates.
 
Derived: trip trajectories (~500B/trip, 20M trips/day), city heat maps (H3-res7, 5-min),
road speed profiles (feeds DeepETA), supply counts per zone per 15-min (feeds surge).

Key consumers:

1. DeepETA: historical road-segment speeds by time-of-day → trained weekly on 90 days of trajectories
2. Surge Pricing: real-time supply density (5-min Flink aggregates) + same-time-last-week patterns
3. City Operations: anonymized heat maps, traffic flow analysis, compliance reporting
4. Safety Platform: trajectory anomaly detection, speed violations, post-incident GPS reconstruction
7

Multi-team rollout

Phased Rollout Plan

Phase 1: Core Pipeline — Single Region (Weeks 1-8)

  • Deploy Gateway + Kafka + Spatial Index in US-East; migrate 1% of US traffic via feature flag
  • Shadow mode: old and new pipelines both process updates, compare freshness and query results
  • Success criteria: p99 < 500ms ingestion, index freshness < 5s, zero data loss

Phase 2: Full US + Map Matching (Weeks 9-16)

  • Ramp US: 1% → 10% → 50% → 100%; deploy Map Match Service and battery SDK to 10% Android
  • Deploy analytics pipeline, backfill from legacy
  • Success criteria: DISCO latency unchanged, map match accuracy > 95%

Phase 3: Multi-Region Expansion (Weeks 17-28)

  • EU (GDPR), APAC (India/SE Asia), LATAM (São Paulo/Mexico City)
  • Cross-region Kafka replication via uReplicator; migrate remaining consumers
  • Success criteria: < 2s cross-region lag, regional autonomy during partitions

Phase 4: Legacy Decommission (Months 7-12)

  • Migrate remaining traffic, decommission legacy, launch predictive location + indoor positioning

Rollback Plan

Stage
Rollback Action
Data Impact
Phase 1 (1% shadow)
Feature flag off, traffic back to legacy
None — legacy was always active
Phase 2 (US ramp)
Gradual ramp-down, legacy remains warm
Dual-write ensures legacy has all data
Phase 3 (multi-region)
Per-region rollback to legacy
Region-specific; other regions unaffected
Phase 4 (legacy decommissioned)
Cannot roll back — must fix forward
Requires emergency re-deployment of legacy if catastrophic

Cross-Team Coordination

Critical path: Kafka provisioning (4w lead) → Gateway deploy → Spatial index → DISCO migration
Parallel path: SDK development, Map matching, Analytics pipeline
Key risk: DISCO migration is last (highest blast radius) — requires spatial index stability proof
8

Bottlenecks & evolution

Bottleneck Analysis

Component
Bottleneck
Mitigation
Location Gateway
CPU at 1.25M/sec for validation + H3
Horizontal scaling, pre-compute H3 on device
Kafka cluster
Hot-spot partitions in dense cities
Dynamic reassignment; H3 res-3 for mega-cities
Spatial Index (Ringpop)
Node failure → rehash ~160K drivers, 5s stale
Replica ring, SWIM fast detection, client retries
Map Match Service
Redis throughput ceiling under load
Region-sharded Redis, in-process LRU for hot segments
Cassandra hot store
Write amplification at 1.25M/sec × RF=3
LSM-tree write-optimized; LeveledCompaction
Cross-region replication
Network partition → replication lag
Bounded lag queue, degrade to regional-only
Mobile SDK (low-end devices)
CPU/memory on $50 Android phones
< 2 MB SDK, native C++ core, avoid allocation

Observability

Key metrics (RED method):

Service
Rate
Errors
Duration
Location Gateway
Updates received + published/sec
Validation, Kafka publish, auth failures
Ingestion latency p50/p99
Spatial Index
Queries/sec, updates applied/sec
Timeouts, stale serves, forwarding failures
Query latency p50/p99, index staleness
Map Match
Locations processed/sec
Low-confidence matches, cache misses
Match latency p50/p99
Kafka
Msgs/sec, consumer lag per group
Produce failures, under-replicated partitions
Produce latency, E2E lag
Analytics Pipeline
Events consumed/sec
Flink checkpoint failures
Event-time to HDFS-write lag
Mobile SDK
Updates generated/sec, battery %/hr
GPS fix failures, network failures
Time-to-first-fix

Critical alerts:

1. Kafka consumer lag > 30s (spatial-index group): DISCO sees stale locations → matching degrades

2. Ingestion drop > 10% vs. baseline by city: Gateway outage or SDK bug; page Mobile Platform team

3. Ringpop membership churn > 5 nodes/min: Possible cascade; pause rebalancing, investigate

4. Map match confidence p50 < 0.7 in any city: Stale road network data; alert Maps team

5. Cross-region replication lag > 60s: Analytics diverging; check inter-region connectivity

Distributed tracing:

  • Write path: SDK.generateUpdate → Gateway.validate → Kafka.produce → SpatialIndex.updateIndex
  • Query path: DISCO.findNearby → SpatialIndex.query → SpatialIndex.filterAndRank
  • Sampling: 0.1% of updates (1,250 traces/sec), 100% of error paths
  • Tags: driver_id, city_id, trip_id; device-side timing reveals per-market network quality

2-3 Year Evolution

Year 1: Foundation and Scale

  • Core pipeline operational across all regions at 1.25M+ updates/sec
  • Spatial index serving DISCO, live map, surge with sub-50ms queries
  • Map matching in top 50 cities; battery-efficient SDK on all driver apps
  • Historical pipeline replacing legacy; ML teams onboarded as consumers
  • Operational maturity: automated runbooks, chaos testing, on-call rotation

Year 2: Intelligence and Prediction

  • Predictive location: ML model predicts driver position in 5 minutes from trajectory + road network + historical patterns. DISCO uses predicted positions for proactive matching (dispatch who will be nearby, not just who is nearby now). New "predicted location" field in spatial index, updated every 30s per driver.
  • Indoor positioning: WiFi fingerprinting + BLE beacons in top 100 airports/transit hubs. Enables precise pickup ("Terminal 2, Door 4" vs. a GPS dot in the parking lot). Requires venue operator partnerships.
  • Edge computing: Push Kalman filter + map matching to vehicle ECU for connected partner fleets. New ingestion protocol for OBD-II / CAN bus telemetry.
  • Cost optimization: Micro-batch Cassandra writes (100/batch) → 40% cluster reduction. Intelligent tiering: high-value markets retain full resolution longer, smaller markets aggregate earlier.

Year 3: Platform and Ecosystem

  • Location-as-a-Platform: Self-service API for Uber verticals (Freight, Health, Connect). Same ingestion → indexing → analytics pipeline, vertical-specific configuration (update frequency, accuracy, retention).
  • V2X integration: Ingest high-frequency vehicle telemetry (10 Hz accelerometer, tire pressure, engine status) — 10x current volume per vehicle. Enables predictive maintenance, road condition sensing, EV fleet energy optimization.
  • Multi-modal tracking: Unified platform for cars, bikes, scooters, trains with entity-type-aware processing (different Kalman parameters, different map matching models per entity).
  • Privacy-preserving analytics: Differential privacy for external aggregates; on-device federated learning for personalized ETA without raw location leaving device.

Cost Optimization Roadmap

Strategy
Timeline
Estimated Savings
Micro-batch Cassandra writes (100/batch)
Month 4
40% reduction in Cassandra cluster cost (~$32K/month)
Kafka partition rebalancing for even load
Month 6
20% reduction in Kafka brokers (~$50K/month)
Aggressive warm→cold data tiering (30-day raw → aggregate)
Month 9
35% reduction in HDFS storage (~$42K/month)
SDK-side H3 computation (offload from gateway)
Month 6
15% reduction in gateway compute (~$11K/month)
Reserved instances for baseline Kafka/Cassandra load
Month 3
30% on committed compute (~$100K/month)
Idle-driver update frequency reduction (30s → 60s for truly idle)
Month 4
15% reduction in overall update volume (~$50K/month)

Summary

The key staff-level insights in this design:

1. H3 hexagonal grid as the universal spatial primitive — partitioning Kafka by H3 cell (not driver_id) aligns data locality with access patterns (DISCO queries by geography), avoids hot-spot partitions, and enables natural sharding of the in-memory spatial index via Ringpop consistent hashing.

1. Tiered freshness model for multi-consumer architecture — rather than one-size-fits-all latency, we serve ride matching from in-memory index (< 50ms), live map via WebSocket with interpolation (< 3s perceived), and analytics from batch pipeline (minutes). This tiering reduces cost by 3-4x vs. serving everything at real-time latency.

1. Battery efficiency as a first-class system constraint — the entire pipeline design (adaptive frequency, batched gRPC, fused location providers) is shaped by the constraint that driver phones must survive 8-hour shifts. A 1% improvement in battery efficiency across 8M drivers has more marketplace impact than a 10% improvement in server latency.

1. Failure domain isolation between ingestion, indexing, and analytics — Kafka decouples the write path (gateway) from all read paths (spatial index, map matching, analytics). Each consumer manages its own failure independently. The spatial index can crash and recover without losing a single GPS update.

1. Map matching transforms raw data into a road-aware signal — the HMM-based map matching pipeline is what makes Uber’s location data valuable beyond simple coordinates. Road-snapped trajectories enable accurate ETA prediction, smooth rider-facing animations, and meaningful traffic analytics. Without it, GPS noise in urban canyons would make the data unreliable.

1. Platform evolution from single-use pipeline to multi-vertical location service — the 3-year trajectory moves from serving ride-hailing to becoming the location backbone for all Uber verticals (Freight, Eats couriers, scooters), amortizing infrastructure cost across the company while maintaining per-vertical configuration flexibility.

Rubric — Senior vs Staff

Dimension
Senior signal
Staff signal
Spatial indexing
Reaches for a geohash or quadtree to find nearby drivers.
Picks H3 hex cells, partitions both Kafka and the in-memory ring by cell, and justifies it over geohash.
Ingestion path
Stateless gateway writes each update onto a queue.
Validates and anti-spoofs at the edge, batches on-device, and sheds idle-driver updates under backpressure.
Freshness model
Serves every consumer from one real-time store.
Tiers freshness per consumer and quantifies the 3-4x cost saved by not serving everything live.
Failure handling
Adds replicas and client retries.
Names failure domains; Kafka decouples write from read so the index can crash and recover loss-free.
Mobile constraint
Notes that sending GPS less often saves battery.
Designs adaptive frequency, fused providers, and batched radio wake-ups around 8-hour shift survival.
★ MORE WALKTHROUGHS

Want more breakdowns like this?

Join free early access for upcoming RAG, LLM eval, agents, and AI infrastructure walkthroughs.

Join Free Early Access →