Skip to content

Case Study 5 — Design Uber

Problem: Design a ride-sharing platform like Uber connecting riders with drivers in real-time, with location tracking, pricing, and payment processing.


TypeRequirement
FunctionalRider request ride, driver accept, real-time location tracking, fare calculation, payment, ratings
Non-Functional< 1s ride match time, < 5s ETA updates, 99.99% uptime, support 25M+ trips/day, global coverage

flowchart TB
subgraph Users["Users"]
Rider["🚗 Rider App"]
Driver["🚕 Driver App"]
end
subgraph Services["Core Services"]
ML["Matching Service"]
Geo["Geospatial Service"]
Pricing["Dynamic Pricing"]
Trip["Trip Service"]
Payment["Payment Service"]
end
subgraph Data["Data Layer"]
Redis_Geo["Redis Geo<br/>Driver locations"]
MySQL["MySQL<br/>Trips, Users"]
Cassandra["Cassandra<br/>Trip history"]
Kafka["Kafka<br/>Events stream"]
end
Rider --> ML
Driver --> ML
Rider --> Geo
Driver --> Geo
ML --> Pricing
ML --> Trip --> Payment
Geo --> Redis_Geo
Trip --> MySQL & Cassandra
Trip --> Kafka
style Users fill:#f59e0b,color:#fff
style Services fill:#7c3aed,color:#fff
style Data fill:#3b82f6,color:#fff

sequenceDiagram
participant Rider as Rider
participant Match as Matching Service
participant Geo as Geospatial Service
participant Driver as Nearby Drivers
Rider->>Match: Request ride at lat/lng
Match->>Geo: Find nearest drivers
Geo->>Geo: Query Redis GEO (radius 2km)
Geo-->>Match: 5 nearby drivers
par Surge Pricing Check
Match->>Pricing: Calculate fare
Pricing-->>Match: $12.50 (distance × time × surge)
end
Match->>Driver: Send ride offer (batch)
Note over Match,Driver: Drivers have 15 seconds to respond
Driver-->>Match: Driver #42 accepted < 2s
alt Multiple Accepts
Match->>Match: Accept first responder
Match->>Driver #42: ✅ Trip confirmed
Match->>Other Drivers: ❌ Trip taken
end
Match-->>Rider: Driver assigned (ETA: 3 min)

1. Geospatial Indexing

Uber uses H3 (hierarchical hexagonal grid) for geospatial indexing — divide the world into hexagons at different resolutions.

SystemHow It WorksProsCons
Redis GEOGeohash-based, radius querySimple, fastSingle-threaded at high QPS
H3Hexagonal grid, pre-computedHighly scalable, consistentComplex setup
Elasticsearch geoGeo-distance queryFull-text + geoSlower for high write volume

2. Dynamic Pricing (Surge)

flowchart TB
RealTime["Real-time supply/demand<br/>per geohash cell"] --> Compare{"Demand > Supply?<br/>by threshold"}
Compare -->|"Yes"| Surge["Apply surge multiplier<br/>1.2x - 5x"]
Compare -->|"No"| Normal["Base pricing"]
Surge --> Incentive["Drivers incentivized<br/>→ Move to surge area"]
Incentive --> Rebalance["Supply rebalanced"]
Rebalance --> Normal
style RealTime fill:#f59e0b,color:#fff
style Surge fill:#ef4444,color:#fff
style Normal fill:#059669,color:#fff

AspectApproachTrade-off
Location updatesDriver app sends GPS every 4 secondsHigh write throughput to Kafka
Ride matchingH3 hex grid, pre-filter by cellGrid boundary edge cases
Real-time trackingWebSocket + Kafka streamConnection management at scale
PaymentSeparate payment service, asyncSettlement delay

  • Ride matching = find nearest driver using geospatial index (H3 hex grid)
  • Real-time location = drivers stream GPS to Kafka, riders subscribe via WebSocket
  • Dynamic pricing adjusts fares based on real-time supply/demand per area
  • Trip service tracks the entire trip lifecycle: request → match → pick up → drop off → payment
  • Kafka is the backbone — events flow between all microservices
  • Consistency is eventual — it’s okay if driver location lags by 2-3 seconds