Design a Ride-Sharing App (Uber/Ola) — Cheat Sheet
System Design Case Studies · 5 topics. Download the PDF or the Instagram carousel and share it.
Cheat Sheet · AiCanCode.org
Design a Ride-Sharing App (Uber/Ola)
System Design Case Studies5 topicsQuick revision reference
1
Requirements
A ride-sharing platform connects passengers to nearby drivers in real time. The system must track millions of moving vehicles, match riders to the optimal driver within seconds, calculate dynamic surge pricing, and manage the full trip lifecycle through a reliable state machine — all at the scale of 25M trips per day.
- ✓Passengers can request a ride by providing pickup and drop-off locations
- ✓The system matches the request to the best nearby available driver within seconds
- ✓Drivers receive ride requests and can accept or decline
- ✓Real-time location tracking of the driver is shown to the passenger during the trip
- ✓Surge pricing is applied dynamically based on local supply/demand imbalance
- ✓Fare estimation is shown to the passenger before confirming the booking
2
Scale Estimates
- ✓Trips / day: 25M ≈ 290 / sec (peak ~1,000 / sec)
- ✓Active drivers: 5M simultaneously online
- ✓Location updates: 5M drivers × 15/min = 75M/min ≈ 1.25M/sec
- ✓Location record size: ~50 bytes (driverId, lat, lng, timestamp, status)
- ✓Location write throughput: 1.25M × 50B ≈ 62.5 MB/sec raw ingestion
- ✓Trip record size: ~1 KB with route + fare metadata
3
Key Components
- ✓API Gateway / Load Balancer — Routes HTTP requests and manages WebSocket upgrade handshakes. Handles JWT authentication, rate limiting, and geographic routing to the nearest regional cluster.
- ✓Location Update Service — Receives driver location pings every 4 seconds via WebSocket or HTTP. Writes to a geospatial index (Redis + geohash) for real-time proximity queries, and publishes events to Kafka for analytics and ETA recalculation.
- ✓Matching Service — On ride request, queries the geospatial index for available drivers within expanding radius rings (500m → 1km → 2km). Scores candidates by proximity, acceptance rate, and rating. Sends offer to the top-ranked driver. If declined or timed out, moves to the next candidate.
- ✓Trip Service — Owns the trip state machine. Persists all trip records to PostgreSQL. Emits state change events to Kafka consumed by notification, billing, and analytics services.
- ✓Surge Pricing Service — Monitors the ratio of active ride requests to available drivers per geohash cell every 60 seconds. When demand exceeds supply by a configurable threshold, a surge multiplier is applied. Multipliers are stored in Redis and served to the Fare Estimation API.
- ✓Geospatial Index (Redis) — Stores current driver positions using Redis GEO commands (backed by a sorted set with geohash scores). Supports GEORADIUS queries for O(log N + M) proximity lookups. Also maintains driver status (AVAILABLE / BUSY / OFFLINE) as a separate hash.
4
Trade-offs
- ✓Geohash vs H3 for spatial indexing → Geohash for matching, H3 for surge pricing: Redis natively supports geohash via GEORADIUS, making proximity queries trivial. H3 hexagons have equal-area cells ideal for uniform supply/demand analysis but require more infrastructure. Use the right tool for each workload.
- ✓WebSocket vs HTTP polling for driver location → WebSocket: 5M drivers sending updates every 4 seconds = 1.25M/sec. HTTP polling adds per-request overhead (headers, connection setup) that is prohibitive at this rate. WebSocket is a persistent connection — the overhead is paid once.
- ✓Redis GEO vs PostGIS for driver location store → Redis GEO: PostGIS is excellent for complex geospatial queries on persistent data. Driver locations are ephemeral and change every 4 seconds. Redis GEO handles millions of point updates/sec in-memory with sub-millisecond GEORADIUS queries. PostGIS would become a write bottleneck.
- ✓Per-driver offer lock vs queue-based matching → Per-driver Redis lock (SET NX EX): A queue-based approach serialises all matching for a region through a single consumer, creating a bottleneck. Per-driver locks are fine-grained — many matches can proceed in parallel across different drivers, with only conflict on the same driver.
- ✓Synchronous fare deduction vs async billing → Async billing via Kafka: Charging the passenger at trip completion involves payment gateway calls that can be slow or fail. Decoupling via Kafka ensures trip completion is acknowledged instantly, and billing retries independently without affecting the user-facing response.
5
Interview Tips
- ✓Lead with scale numbers. 5M drivers × 15 pings/min = 1.25M writes/sec is the hardest problem — state it upfront and design the location update pipeline around it.
- ✓Interviewers love the geohash question. Explain that a 6-character geohash is ~1.2km × 0.6km and proximity = same prefix + 8 neighbours. Mention the edge case where neighbouring cells can have different prefixes.
- ✓Draw the trip state machine explicitly: REQUESTED → DRIVER_ASSIGNED → DRIVER_ARRIVED → IN_PROGRESS → COMPLETED. Interviewers expect you to handle the state transitions and what happens at each.
- ✓The distributed offer lock (Redis SET NX EX) is a key insight. Without it, two passengers could be matched to the same driver simultaneously.
- ✓Surge pricing: explain that the multiplier is a function of demand/supply ratio per geographic cell, stored in Redis, and smoothed to avoid jarring jumps.
- ✓When asked about ETA, mention that road network graph queries (OSRM) are expensive — pre-compute ETAs for the top N candidates rather than all drivers in radius.
Learn this free with Aria, your AI tutor → AiCanCode.org/learn/system-design-cases