Skip to content

Design a Ride-Sharing System (Uber)

A ride-sharing system like Uber connects riders with nearby drivers in real-time.


Functional:

  • Rider requests a ride
  • Find nearby drivers and match
  • Real-time location tracking
  • Fare calculation
  • Ride completion and payment

Non-functional:

  • Location updates every 3 seconds
  • Match a driver within 100ms
  • Support 10M daily rides
  • Handle spikes (New Year’s Eve → 10× normal)

flowchart LR
Rider["👤 Rider"] --> API["API Gateway"]
Driver["🚗 Driver"] --> API
API --> Geo["Geolocation Service"]
API --> Match["Matching Service"]
API --> Trip["Trip Management"]
API --> Pricing["Pricing / Surge"]
Geo --> Redis[("Redis<br/>Driver locations<br/>Geo-indexed")]
Match --> Redis
Match --> Queue["Message Queue"]
Queue --> Drivers["🚗 Push to nearest drivers"]
style Rider fill:#7c3aed,color:#fff
style Driver fill:#4f46e5,color:#fff
style API fill:#6366f1,color:#fff
style Geo fill:#8b5cf6,color:#fff
style Match fill:#059669,color:#fff
style Redis fill:#059669,color:#fff

Redis has built-in geospatial indexing:

GEOADD drivers:locations 13.4050 52.5200 "driver_123" # Berlin
GEOADD drivers:locations -73.9352 40.7306 "driver_456" # NYC
GEORADIUS drivers:locations 13.4000 52.5200 5 km
→ ["driver_123", ...] # Drivers within 5km

Why Redis? Sub-millisecond queries, built-in geo commands, handles 100K+ location updates/second.


  1. Rider requests ride → query Redis for nearest drivers
  2. Return top N candidate drivers
  3. Push notification to candidate drivers (they have ~15 seconds to accept)
  4. First driver to accept gets the ride
  5. Notify rejected drivers (“ride no longer available”)

Surge pricing: When demand > supply in an area, multiply fares by 1.5×, 2×, etc. to incentivize more drivers to move into that area.


sequenceDiagram
participant Driver as 🚗 Driver App
participant API as 🖥️ API Server
participant Redis as 💾 Redis
participant Rider as 👤 Rider App
loop Every 3 seconds
Driver->>API: Update location (lat, lng)
API->>Redis: GEOADD driver:loc driver_id lat lng
API-->>Rider: Push location update via WebSocket
Rider->>Rider: Update map marker
end

BottleneckSolution
Location write volume10M drivers × 3s = 3.3M writes/sec → Redis Cluster
Matching latencyGeo-indexed Redis + nearest-driver algorithm
Driver glutToo many drivers nearby → only notify top 10
FraudVerify ride started from match location

Q: What happens when a driver’s or rider’s GPS signal drops mid-trip? The app falls back to the last known location plus dead-reckoning from device sensors (speed, heading) for a short window, and the trip continues on a stale-but-plausible position. If the gap exceeds a threshold (e.g., 30-60s with no update), flag the trip for manual review rather than silently trusting extrapolated coordinates.

Q: How do you handle a region with far more riders than drivers, beyond just raising surge price? Surge alone doesn’t create supply instantly, so combine it with driver incentives to reposition into the zone (bonus for accepting rides that end near the shortage), temporarily widening the matching radius, and rider-side signals like longer ETAs or ride-pooling suggestions to reduce demand pressure.

Q: How do you prevent GPS spoofing for fraud (fake rides, fare manipulation)? Cross-check reported GPS against network-based location (cell tower/WiFi triangulation) and flag mismatches. Also validate physical plausibility — speed between consecutive location pings can’t exceed realistic travel speed — and require the trip start location to match the matched pickup point within a tolerance.

Q: What if two drivers accept the same ride request at the same time (race condition)? Use an atomic compare-and-swap on the ride’s status in Redis/DB (e.g., SETNX or a conditional update) so only the first accept wins; the second driver’s accept fails the conditional check and they get the “ride no longer available” response already built into the flow.

Q: How do you handle a driver going offline mid-trip (app crash, phone dies)? The trip state machine treats missing location pings past a timeout as “driver unreachable,” notifies the rider, and after a grace period allows support to intervene or auto-complete the trip using the last known fare calculation, since payment must still be reconciled.


  • Uber = real-time location tracking + fast nearest-driver matching + payment.
  • Redis geo-indexing is the key to finding nearby drivers in milliseconds.
  • Surge pricing balances supply and demand — more money → more drivers.