System Design: Uber (25M Rides/day, H3 Driver Index, Batch Matching, Exactly-Once Dispatch)
1. The Problem in One Page
1.1 One Ride
Emma is outside a subway station in New York and opens the app. Every online driver's phone has been sending its position every few seconds, so the system already has a live map of free drivers.
The app shows her a price and a pickup time. To make them, the system found the free drivers near her and asked how long the nearest would take by road. It also checked how many people nearby want rides, and holds that price briefly.
She taps Request. Her signal is weak, so the app sends the request twice. The system must save her trip once, and in a way that can't be lost.
Then it waits a moment, to decide for all the riders asking nearby together. It picks Mike, a driver a few streets away, and sends him an offer.
While Mike decides, nobody else may be given Mike.
He accepts. Emma watches his car move on her map, with an updating arrival time. When he ends the trip, the system works out the fare and charges her card once. It records who is owed what, and pays Mike.
1.2 Why This Is Hard
It sounds like one query. Find the nearest free car and send it. At this size it breaks in five ways.
- Drivers never stop moving. A huge number of phones send positions all the time, and each one is soon out of date.
- Near means road time. A driver across a river looks close on the map but may be far away by road.
- Riders compete for drivers. Riders near each other see the same few cars, and one driver must never be promised to two of them.
- Phones are unreliable, but money must be exact. A retry must never book two cars or charge a card twice.
- Every city has its own rules. Fares, search distance and surge limits differ by city, some set by law.
1.3 Mistakes This Design Avoids
- Locking a driver in a cache. Redis copies to its backup in the background. In a failover the lock can vanish, and two riders get one driver.
- Matching each rider to their nearest driver, one at a time. The first rider can take the car the next rider needed.
- Storing every GPS point in a SQL database. Each position is replaced seconds later, so disk writes on it are waste.
- Trusting the order GPS points arrive in. Old points sent after a tunnel would move a driver backwards.
- Saving the trip and sending the event as two steps. A crash between them leaves the system disagreeing with itself.
- One global system, or a full copy per city. The first puts phones far away and spreads one bad change everywhere. The second pays for thousands of tiny copies.
2. Requirements and Scale
2.1 Functional Requirements
| ID | Requirement | Priority |
|---|---|---|
| FR-01 | A rider gets a fare quote and a pickup time before booking. The quoted price is held for a short time. | P0 |
| FR-02 | A rider requests a ride from a quote. A retried request books one ride, not two. | P0 |
| FR-03 | The system matches the rider with a nearby free driver, using road time to the pickup | P0 |
| FR-04 | The driver gets an offer and accepts or declines it within a time limit. On decline or no answer, the rider is offered another driver. | P0 |
| FR-05 | A driver goes online and offline. While online, the driver app sends its position every 4 seconds. | P0 |
| FR-06 | The rider sees the driver's car move on the map, with an arrival time that updates | P0 |
| FR-07 | The driver marks arrived, start trip and end trip | P0 |
| FR-08 | The rider is charged once at the end, the driver is paid, and both get a receipt | P0 |
| FR-09 | A rider or a driver cancels. A cancel fee applies by the city's rules. | P0 |
| FR-10 | Prices go up in areas where demand is higher than supply (surge), within each city's legal cap | P1 |
| FR-11 | A rider with the app open sees free cars nearby on the map | P1 |
| FR-12 | Each city has its own settings: fares, surge cap, search radius, batch window, offer timeout | P1 |
| FR-13 | Rider and driver rate each other after the trip | P2 |
| FR-14 | Rider and driver see their past trips | P2 |
2.2 Non-Functional Requirements
p99 is the time that all but the slowest 1% of requests beat. Times are measured inside our servers, without the phone's network.
| Requirement | Target | Why it matters |
|---|---|---|
| Booking to first offer | Under 3 s at p99, with a free driver near | A rider with no news gives up |
| Quote and booking | Under 300 ms and 500 ms at p99 | The only moments the rider waits |
| One driver promised to two riders | Never | One rider waits for a car that never comes |
| A booked ride lost | Never, once there's a trip id. A retry returns the same trip. | The rider was told "booked" |
| Money | Charged exactly once, at the quoted price unless the trip changes | Real money from a real person |
| Requests accepted | 99.99% a month in each city | About four minutes of outage a month |
| One data centre lost | Affected cities pause matching for about 12 s | A short delay, not an error |
| A whole region lost | Matching back from the backup region within 5 minutes. No trip or money lost. | Rare, but it can't erase rides |
| Freshness | Car on the map every 4 s, arrival time every 10 s | The car must look alive |
| Driver positions, waiting riders, surge | May be lost. They rebuild within about a minute. | This lets the fast parts skip copying |
Read the last row next to the "never" rows. The live map may vanish, because it rebuilds from the next few GPS points. Trips may not. And "never", not "rarely", for double booking decides how drivers are reserved.
2.3 The Numbers We Design For
These inputs are ours, not Uber's. Each number is tied to the decision it drives.
Ride requests. 25 million rides a day is about 290 a second. The busiest hour runs at about 2.5 times that, so about 720 rides a second. Some requests never become rides (no driver, a cancel, a retry), so we plan 1.2 requests per ride.
That's about 870 ride requests a second worldwide. That's small, so the hard load is elsewhere.
Driver locations. Each ride keeps a driver busy for about 23 minutes, counting the drive to the pickup. Little's law says the number busy at once is the start rate times how long each lasts. So 720 rides a second keeps about 1 million drivers busy.
If 60% of online drivers are busy, about 1.66 million are online, each sending a point every 4 seconds.
That's about 416,000 location points a second. This number shapes the design. It's why positions live in memory, behind a queue.
The biggest city. Matching is per city, so the biggest city sets its limits. We give it 4% of rides with a sharper local peak, so about 40 requests a second. A 2-second batch then holds about 80 riders, which takes about a millisecond to solve.
How wrong can these be? One bad guess could make the location rate about 1.5 times higher. So every part is planned at 60% of what it can really do.
2.4 Out of Scope
Shared rides, delivery and scheduled rides. Driver sign-up and checks. Building the map. Training the ETA and pricing models. Fraud and GPS spoofing models. Support, chat, tips and promotions.
3. High-Level Architecture
๐ Premium section
4. How the World Is Split: Cities and Regions
๐ Premium section
5. Tech Choices and Why
๐ Premium section
6. Deep Dive: The Location Path
๐ Premium section
7. Deep Dive: Finding Nearby Drivers
๐ Premium section
8. Deep Dive: ETA, Road Time
๐ Premium section
9. Deep Dive: Matching Riders to Drivers
๐ Premium section
10. Deep Dive: Reserving a Driver Without Double Booking
๐ Premium section
11. Deep Dive: The Trip's Life, and Events
๐ Premium section
12. Deep Dive: Prices, Surge and the Quote
๐ Premium section
13. Deep Dive: Payments and the Ledger
๐ Premium section
14. Live Updates to Phones
๐ Premium section
15. Capacity
๐ Premium section
16. What Happens When Each Part Goes Down
๐ Premium section
17. Bottlenecks and How to Fix Them
๐ Premium section
18. Regions and Scaling
๐ Premium section
19. Running It
๐ Premium section
20. Trade-offs, and What Is Standard
๐ Premium section
21. Questions You'll Get Asked
๐ Premium section
How We Measured
๐ Premium section
Explore the Technologies
๐ Premium section