Design Uber  πŸš•

rider ⇄ driver matching Β· real-time location Β· hellointerview breakdown

1Requirements

Functional

  • Pickup + dest β†’ fare estimate
  • Request ride from that estimate
  • Match rider ↔ nearby available driver
  • Driver accepts/declines β†’ pickup β†’ dropoff

βœ— ratings, scheduling, ride tiers

Non-functional

  • Match < 1 min β€” or fail
  • Strong consistency β†’ 1 driver, 1 ride
  • Peak: 100k reqs, same location

βœ— GDPR, redundancy, CI/CD

2Entities & data model

Ride  rideId Β· riderId Β· driverId? Β· fareId
        source Β· destination Β· status
Fare  id Β· userId Β· source Β· destination
        price Β· eta

Driver  id Β· name Β· vehicle
Rider   id Β· …
Location  driverId Β· lat/long Β· ts

driverId is nullable until matched

Fare = the quote Β· Ride = the trip Β· Location = the hot, high-write one

status: requested β†’ matched β†’ accepted β†’ in-progress β†’ completed

3API

POST /fare {pickupLocation, destination} β†’ Fare  getFareEstimate()
POST /rides {fareId} β†’ Ride
POST /drivers/location {lat, long} β†’ OK   updateLocation()
PATCH /rides/:rideId {accept | deny} β†’ Ride  acceptOrDeclineRide()

β˜… Never take driverId/riderId from the body β€” read it from the JWT. A client-supplied id lets anyone move any driver.

4High-level design

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ 3rd-party Maps ◀─┐ Rider ─┐ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”œβ”€β”€β–Άβ”‚ API GATEWAY │──▢ RIDE SERVICE ─────────────▢ DB (Dynamo/Postgres) Driver β”€β”˜ β”‚ routingΒ· auth β”‚ fare est Β· create ride Fare + Ride β–² β”‚ rate-limit β”‚ triggers match workflow β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ [ MATCH QUEUE ] β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”Œβ”€β–Ά DISTRIB. LOCK (Redis) β”‚ β”‚ MATCHING SERVICE ─── "driver already asked?" β”‚ β”‚ └─▢ LOCATION DB (Redis) β”‚ └──▢ LOCATION SERVICE ─────────────▢ "closest drivers" β”‚ updateLocation() └── NOTIFICATION SVC (APNs/FCM) ◀── "accept / decline?"

β˜… Redis appears twice β€” different jobs

Uber Β· pg 1/2

Deep dives

the part the interview is actually scored on

1Geospatial β€” 2 M writes/sec

Why it breaks: B-trees order in 1-D. "Drivers within 2 km" is a 2-D range query β€” the index can't serve it.

alt (good, not great): Postgres + PostGIS, quadtree index

2Adaptive ping intervals

3Double-booking a driver

Race: two Matching instances pick the same driver at the same instant.

lock(driverId, TTL 10s) β†’ notify β†’ accept β†’ update ride + release
                    β””─ silence β†’ TTL expires β†’ driver free

4Peak demand β€” lose nothing

5Driver doesn't respond

6Scaling for latency

Level bar

  • E4: working HLD, know you need a geo index, some driver lock
  • E5: 2+ deep dives in detail, argue trade-offs
  • L8+: raise 3+ unprompted, from real experience

Recall in 20 s

Redis geohash β†’ 2M w/s Β· lock + TTL β†’ no double-book Β· Kafka, late offset commit β†’ no lost reqs Β· durable workflow β†’ timeouts Β· geo-shard β†’ latency.

Uber Β· pg 2/2