System Design Interview: Design a Ride-Sharing App (Uber/Lyft)

System Design: Design a Ride-Sharing App (Uber/Lyft)

Designing Uber or Lyft is one of the most popular system design interview questions. It combines real-time geospatial queries, matching algorithms, dynamic pricing, and high-throughput event processing.

Requirements

Functional: rider requests a ride with pickup/dropoff, system matches a nearby driver, real-time tracking during the trip, dynamic surge pricing, trip history and payments.

Non-functional: match within 30 seconds, handle 1M+ concurrent users, location updates every 4 seconds per driver, sub-second driver lookup within radius, global availability.

Key Components

Rider App                     Driver App
    │ request ride                 │ location ping (every 4s)
    ▼                             ▼
┌────────────────────────────────────────────────┐
│  API Gateway / Load Balancer                   │
└──────────────────┬─────────────────────────────┘
                   │
     ┌─────────────┼─────────────┐
     ▼             ▼             ▼
Location       Matching       Trip
Service        Service        Service
(geospatial)   (dispatcher)   (state machine)
     │             │             │
     ▼             ▼             ▼
Redis Geo       PostgreSQL    Kafka
(driver pos)    (trips DB)    (events)

Location Service — Driver Position Tracking

Drivers send GPS updates every 4 seconds. At 1M active drivers: 250K location updates/second.

  • Redis GEO commands: GEOADD stores (longitude, latitude, member) as a sorted set with geohash scores. GEORADIUS returns all members within a radius in O(N+log(M)) — perfect for finding nearby drivers.
# Driver sends location update
redis.geoadd("drivers:active", longitude, latitude, driver_id)
redis.expire(f"driver:{driver_id}:location", 30)  # expire if driver goes offline

# Find drivers within 2km of pickup
nearby = redis.georadius(
    "drivers:active",
    pickup_lng, pickup_lat,
    radius=2, unit="km",
    withcoord=True,
    withdist=True,
    count=50,           # limit candidates
    sort="ASC"          # nearest first
)

Scaling: shard the drivers sorted set by geohash prefix (city or region). Drivers in NYC update drivers:active:nyc, drivers in LA update drivers:active:la.

Matching Service (Dispatcher)

  1. Rider requests ride with pickup + dropoff + ride_type
  2. Query Location Service for N nearest available drivers (radius 2km, expand to 5km if none)
  3. Filter by: vehicle type, driver rating, acceptance rate
  4. Rank by: ETA (estimated time of arrival) — requires road network routing
  5. Send offer to best driver (1 driver at a time or top-3 simultaneously)
  6. If driver accepts within 15s → assign; if declines or times out → next driver
  7. Timeout after 3 rounds → notify rider no drivers available

ETA Calculation

  • Simple: straight-line distance / average speed × traffic factor. Fast, ~500ms.
  • Accurate: road network graph (Dijkstra / A*) with real-time traffic weights. Uber uses a custom routing engine (H3 hexagonal grid). Slower but precise.
  • Pre-compute ETAs for driver-to-pickup pairs in batch; serve from cache for common pairs

Trip State Machine

States:
REQUESTED → MATCHED → DRIVER_EN_ROUTE → ARRIVED → IN_TRIP → COMPLETED
                                                           └→ CANCELLED

Transitions stored in Kafka (event log) + PostgreSQL (current state)
Each state change emits an event to notify rider and driver apps via WebSocket/push

Dynamic Surge Pricing

  • Compute demand/supply ratio per geohash cell every 1 minute
  • surge_multiplier = f(demand / supply) — Uber uses 1.1x, 1.5x, 2x, 3x tiers
  • Display surge estimate before booking; require rider to confirm surge rate
  • Store surge history for analytics and model training

Payment Flow

  • Upfront price estimate: base fare + per-mile + per-minute + surge + booking fee
  • Final charge at trip end with actual distance/duration
  • Payment processor: Stripe or Braintree; supports multiple methods (card, wallet, cash)
  • Driver payout: weekly batch settlement, instant payout for premium drivers

Interview Checklist

  • Draw: Location Service (Redis GEO) → Matching (dispatcher) → Trip (state machine)
  • Explain Redis GEOADD/GEORADIUS for O(1) driver storage, O(log n + k) radius query
  • Describe the matching loop: offer → 15s timer → next driver
  • Cover surge pricing: demand/supply ratio per geohash cell
  • Mention scalability: shard drivers by city, use WebSocket for real-time tracking

  • Airbnb Interview Guide
  • Meta Interview Guide
  • Stripe Interview Guide
  • DoorDash Interview Guide
  • Lyft Interview Guide
  • Uber Interview Guide
  • 🏢 Asked at: Snap Interview Guide

    Scroll to Top