Design Uber or Lyft
Match riders with nearby drivers and track every trip live.
Asked at Uber, Lyft and 3 more
3 min read·8 sections
Uber and Lyft match a rider with a nearby driver in seconds, then track the trip live until drop-off. The system revolves around location: millions of drivers send their position every few seconds, and the matching service must find the closest available ones instantly.
Requirements#
Functional
- Riders request a ride from a pickup point and see a price estimate.
- Nearby available drivers get the request; one accepts.
- Both see each other's location live during the trip.
- Payment happens automatically at the end.
Non-functional
- Match a driver within seconds.
- Location updates are processed with low latency, at high volume.
- A driver must never be assigned two rides at once.
Estimates#
Location updates dominate, and they are short-lived: only the latest position matters.
Indexing locations#
Scanning every driver for each request is impossible. We need a spatial index:
- Geohash turns latitude and longitude into a string where nearby points share a prefix. Find the rider's cell, then look at that cell and its neighbours.
- Quadtrees split dense areas into smaller cells.
- H3, Uber's hexagonal grid, has neighbours at equal distances, which makes radius searches and surge pricing by area cleaner.
Architecture#
- Location service: writes each driver's latest position into an in-memory geo index (Redis
GEOADD, or custom cell maps) with a short TTL, so drivers who go offline drop out automatically. - Matching: finds available drivers near the pickup, ranks them by ETA (road distance, not straight-line), and offers the ride to the best one.
- Trips DB: durable trip records, payments and history in a relational database.
Matching without double-booking#
Two matchers could pick the same driver at once. Make the assignment atomic:
SET driver:812:lock ride:5531 NX PX 15000Only one ride gets the lock. If the driver declines or the offer times out after about 15 seconds, the lock expires and the next driver is offered the ride.
Live trip tracking#
During a trip, the driver's location updates are forwarded to the rider over a WebSocket. Updates also go to Kafka for ETA models, fraud checks and later billing by actual route.
Partitioning by city#
Rides are local, so shard the location index and matching by city or region. Each region scales on its own, and a failure in one city doesn't affect another.
Surge pricing#
Compare demand (open requests) with supply (available drivers) per cell every minute or so, and raise prices where demand outstrips supply. This also nudges drivers toward busy areas.
Finished this walkthrough?
Mark it as read to track your progress in the list.