01What does the rider see first — a price before they commit?
Riders enter pickup and destination and get a fare estimate (price + ETA) before requesting the ride.
Free full guide
Design Uber — a ride-hailing platform matching riders to nearby drivers in real time, with live location tracking, pricing, and trip lifecycle management.
The interview rhythm stays compact, so the page can spend attention on the actual design decisions.
Do not only state requirements. Ask for them. Each card pairs the design constraint with a clarification question you can say out loud before drawing the architecture.
01What does the rider see first — a price before they commit?
Riders enter pickup and destination and get a fare estimate (price + ETA) before requesting the ride.
02What happens after they tap request — how fast must a match come back?
Riders request a ride at the estimated fare and get matched to a nearby available driver within about a minute. If no driver is available, they get a clear failure instead.
03What does the driver side do?
Drivers go online, send location pings, and receive one ride offer at a time to accept or decline. On accept, they navigate to pickup and drop-off.
04Can a rider cancel after matching, and what does the driver experience?
Yes. After a cancellation, the driver immediately becomes available for new rides, and the system records who cancelled and when.
05Does the rider watch the driver approach live?
Yes. The driver's location streams to the matched rider only while the ride is active. Everyone else sees rough availability, never a trackable trail.
06No driver accepts inside the matching window - then what?
The request fails clearly with retry guidance - a definite no within the minute beats a spinner that never resolves.
Out of scopeRatings (rider and driver) · Scheduled rides and ride tiers (X/XL/Comfort) · Surge pricing mechanics and payment settlement
01Can one driver ever get two rides at once?
Matching is strongly consistent: a driver holds at most one active offer or ride at a time — no double-dispatch, ever.
02How fresh do driver locations need to be?
Drivers ping every few seconds while online; proximity search may see data a few seconds old, never minutes.
03What peak rate of driver location updates should we design for?
We design for a deliberate stress ceiling: 10M drivers online worldwide, each pinging every ~5 seconds. That works out to about 2M location writes per second.
04What happens when a stadium lets out?
A burst of ~100K ride requests from one area queues and drains gracefully — nearby zones and other cities stay unaffected.
05How fast should each step feel?
Fare estimate in a couple of seconds; match (or a clear failure) within about a minute end to end.
Real interviews probe far more than a tidy list. These are the scope questions that separate candidates who interrogate the problem from those who recite it.
Treat every estimate as a pressure that justifies a component: cache, queue, partition, replica, worker pool, or fallback path.
Location write firehose
a stress ceiling of 10M drivers online worldwide × 1 ping every 5 s10,000,000 ÷ 5 ≈ 2M writes/s
No relational database absorbs this — locations go into an in-memory geo index (geohash/H3 buckets) with TTL eviction.
Proximity lookup cost
The pickup point lands in one geohash cell; covering the search radius means that cell plus its 8 neighbors — a 3 × 3 grid, 9 cells9 cell reads × well under 1 ms per in-memory lookup ≈ single-digit milliseconds
Geohashing turns "who is near me" into a handful of key lookups instead of a table scan.
Concert burst
~100K requests from one neighborhood over ~10 minutes100,000 ÷ 600 s ≈ 170 matches/s in one zone
Partition the matching queue by geo zone — the spike saturates one zone’s consumers, not the whole city.
Offer budget
Match within 60 s; each offered driver gets ~10 s to respond60 s ÷ 10 s ≈ 5-6 drivers tried before the deadline
The 10-second offer lock limits how many drivers you can try inside the minute. So rank candidates well instead of spraying offers.
Phantom-driver cleanup
Location entries expire 15-30 s after the last ping — that is 3-6 missed pings at the 5 s cadence15-30 s ÷ 5 s per ping = 3-6 silent intervals → entry expires; a crashed driver stops receiving offers within ~30 s at worst
Drivers who crash or go offline vanish from the index on their own — no cleanup job, no offers to ghosts.
Decision example
This system carries two very different loads. Drivers stream in about 2M location writes per second. Each ride match only needs a handful of nearby candidates within a minute.
Keep driver locations in an in-memory geo index (geohash/H3 buckets) with a short TTL, so drivers who stop pinging simply disappear. Matching pulls nearby candidates and offers the ride to one driver at a time, locking that driver for about 10 seconds. Accept wins the ride; a timeout or decline releases the lock and the next candidate gets the offer. During a spike, ride requests wait in a queue partitioned by area, so a stadium letting out slows that neighborhood, not the whole city.
What I would NOT do: write every location ping into the main database and scan it to find nearby drivers. At 2M writes per second, that plus the scans kills it. I also would not offer one ride to several drivers at once without a lock, because two accepts can arrive together and both drivers think they got the job. And I would not shard the matching system on day one. Measure the per-zone rate first; sharding too early adds failure modes without adding capacity you actually need.
If match quality matters more than speed, like pooled rides or batching, I would collect requests for a few seconds and match them in small batches instead of one at a time.
One complete picture first, then each path as its own diagram — the write path and the read path carry different traffic and justify different components.
Complete picture
Driver pings flow straight into the in-memory geo index; matching reads nearby candidates from it and offers rides one driver at a time. Ride truth lives in the database — the index is disposable.
Path 1
Fare first, then request. Matching pulls a handful of nearby candidates and offers one driver at a time; the 10-second lock prevents double-dispatch and moves on automatically when a driver ignores the offer.
Path 2
About 2M pings per second land in memory, bucketed into geohash/H3 cells; entries expire after 15-30 seconds so drivers who stop pinging vanish on their own.
Before optimizing, make the contract inspectable: endpoints, entities, ownership, retries, and state.
POST/fare
req{ pickup, destination }
res200 { fare_id, estimated_fare, eta }
Calls the mapping provider for route + ETA; the estimate is saved so the ride request can reference it.
POST/rides
req{ fare_id }
res201 { ride_id, state: requested } · 404 fare expired
Kicks off matching; the rider gets the match result pushed (or polls).
POST/drivers/location
req{ lat, lng }
res200
Driver identity comes from the session token, never the request body. High-frequency write straight into the geo index.
PATCH/rides/{ride_id}
req{ accept | decline }
res200 ride · 409 offer expired
Accept flips the offer atomically; decline or a 10-second timeout releases the driver and the next candidate gets the offer.
Core entities
Riderrider_id (PK) · payment_profile
Driverdriver_id (PK) · vehicle · status: offline/available/offered/on_trip
The status field is the double-dispatch guard: only an available driver can receive an offer, and the flip is atomic.
Farefare_id (PK) · pickup · destination · estimated_fare · eta
Created at estimate time; the ride request references fare_id so the quoted price cannot silently change.
Rideride_id (PK) · rider_id · driver_id · fare_id · state: requested/matched/in_progress/completed
DriverLocationdriver_id · lat/lng · updated_at
Lives in the in-memory geo index (geohash/H3 cells with a TTL), not the relational store — it is disposable data.
Pick one lane for the final third of the interview. Each lane gives you the topic, the interviewer question it should answer, and the failure mode to avoid.
10M drivers ping every 5 seconds. Where do 2M writes per second go, and how do you answer "who is near this pickup"?
Pings go to an in-memory geo index, never the relational database. It can't take 2M writes a second. Bucket each location into a geohash or H3 cell with a short TTL. To find who's near a pickup, read that cell plus its 8 neighbors — nine memory lookups in single-digit milliseconds, not a table scan.
Writing pings to the main database and scanning for proximity — it dies at this rate.
Two ride requests want the same nearby driver at the same moment. How does exactly one win?
Grab the driver with a short exclusive lock. It's an atomic compare-and-set, so exactly one request wins and the loser moves to its next candidate. The database holds the real ride state: accept flips the driver to on-ride, and a cancellation releases them back to available so no stale hold lingers.
Offering to many drivers at once with no lock — two accepts both think they won.
The offered driver ignores the request. What happens at second 10, and how does the ride still match inside a minute?
The offer is a 10-second lock, not a blocking wait. At second 10 it expires on its own and matching moves to the next ranked driver. At about 10 seconds each, 5-6 drivers fit inside the 60-second budget. That's why you rank candidates carefully instead of spraying offers everywhere.
Blocking the ride on one unresponsive driver instead of a lock TTL that moves on.
100K people request rides from one neighborhood in minutes. How do you keep the rest of the city unaffected?
Partition the matching queue by geo zone. 100K requests over 10 minutes is only about 170 matches per second. It saturates that one zone's consumers while every other zone drains normally. The hot zone sees honest queueing — a longer wait or a clear failure. The rest of the city runs fine.
One global matching queue — a local spike becomes a citywide outage.
A driver app crashes while marked available. How long can they still receive offers, and what cleans them up?
Every location entry expires 15-30 seconds after the last ping. At the 5-second cadence that's just 3-6 missed pings, so a crashed driver drops out of the index on its own. No cleanup job is needed. The longest a ghost can keep getting offers is about 30 seconds.
No TTL on location entries — offers keep going to drivers who left an hour ago.
Talk through Uber (Ride Hailing) out loud and get AI scoring on the explanation.