Question Breakdowns

Ride Sharing

A worked system design: match a rider to the nearest available driver, track the trip in real time, and handle the matching race. Geo indexing of moving drivers, dispatch, and trip lifecycle.


A ride-sharing service (think Uber/Lyft) connects a rider who wants a trip with a nearby available driver, then tracks that trip from pickup to drop-off. It combines three hard pieces: indexing thousands of moving drivers by location, matching a request to the best driver without double-assigning, and real-time tracking of a live trip. It builds directly on Proximity Search and Real-time Updates.

1. Requirements

Functional:

  • Drivers broadcast their location while available.
  • A rider requests a trip; the system matches a nearby available driver.
  • Both parties track each other and the trip in real time (ETA, live location).

Non-functional:

  • Real-time — matching in seconds; live location updates continuously.
  • Correct matching — a driver is assigned to at most one trip; no double-booking.
  • Scale — millions of drivers pinging location every few seconds is a write firehose.
  • Geo queries ("nearest available drivers") must be fast.

2. The moving-drivers problem

Every active driver sends a GPS ping every few seconds — a huge write volume — and you must answer "which available drivers are near this pickup?" instantly. A relational table updated per ping would melt. Instead, keep current driver locations in an in-memory geo index (Redis geospatial, or a quadtree/geohash structure):

driver ping → update driver's current cell/point in the geo index (overwrite, not append)
rider request → query geo index for available drivers within radius R of pickup

You overwrite each driver's position rather than storing history — you only care about where they are now. The location store is ephemeral and fast; durable trip data lives elsewhere.

3. Matching (and the race)

Finding candidate drivers is the geo query; choosing and claiming one is the interesting part:

  1. Query the geo index for available drivers near pickup.
  2. Rank them (distance/ETA, rating) and offer the trip to the best one.
  3. Atomically mark that driver as matched so a concurrent request can't grab the same driver — a conditional update / lock on the driver's state (contention), exactly like holding a seat in Ticket Booking.
  4. If the driver declines or times out, release them and offer to the next candidate.

The dispatch is an offer-and-confirm loop, not a blind assignment — drivers can decline, so the match isn't final until the driver accepts, and the driver's "available → offered → on-trip" state must be changed atomically.

4. The trip lifecycle

Once matched, a trip is a small state machine (a multi-step process):

requested → matched → driver en route → rider picked up → in trip → completed → paid

This lives in a durable store (the source of truth for billing and support), separate from the ephemeral location index. Payment at the end is its own payment flow.

5. Real-time tracking

Both sides hold a real-time connection (WebSocket). The driver's location pings are relayed to the matched rider so they watch the car approach; ETA recomputes as the driver moves. Status transitions (arrived, started, completed) push to both. During a trip you only relay location to the one matched rider, not broadcast it — far cheaper.

6. Deep dives

  • Geo-sharding: partition the location index by region/city so a dense city doesn't overload one node, and queries only touch the relevant region (Sharding).
  • Surge pricing: compute supply/demand per area from the same live data; a pricing multiplier layered on top.
  • Driver ping volume: throttle ping frequency, batch updates; the geo index write must be cheap (overwrite one key).
  • Matching quality: balance nearest-driver against global efficiency (don't strand areas); a dispatch optimiser can look a little ahead.

What to emphasise

Lead with the moving-driver geo index and the atomic match:

"Drivers ping location constantly, so I keep current positions in an in-memory geo index — Redis geospatial or a geohash/quadtree — overwriting each driver's position rather than storing history, because I only need where they are now. A rider request becomes a radius query for nearby available drivers; I rank by ETA and offer the trip, atomically flipping the chosen driver's state to 'offered' so two requests can't grab the same driver. It's an offer-confirm loop since drivers can decline. The trip itself is a durable state machine for billing, and live location streams to just the matched rider over a WebSocket. I'd geo-shard the location index by city to scale."


Next up: Web Crawler — fetching the web politely and at scale.