#Introduction
The interviewer says: "Design Uber."
The simple version is a map and a database. The real version is a regional real-time system where drivers move every few seconds, riders request rides concurrently, and one driver cannot be assigned twice.
Ride sharing combines geospatial indexing, high-write location tracking, marketplace matching, and strong assignment consistency.
Ready to practice? Try the Ride-Sharing practice problem and build this system step-by-step with AI-guided feedback.
Related concepts for this design: Regional Routing and Geo-Partitioning, WebSockets & Real-Time Communication, Sharding, Distributed Transactions, and Proximity Service.
#Functional Requirements
1. Match riders to nearby drivers
- Rider submits pickup and destination
- System finds nearby available drivers
- System estimates fare and ETA
- System offers the ride to a driver
- Driver accepts or times out
Matching uses ride dispatch: find candidates, reserve one driver atomically, and move the ride through a state machine.
2. Track driver locations
- Drivers send location updates every 2-4 seconds
- Riders can see assigned driver movement
- Matching sees fresh driver availability
Use a high-write location tracking path backed by a TTL location index, not the primary transactional database.
#Non-Functional Requirements
Assignment consistency
One driver must not be assigned to two rides. Candidate search may be stale, but final reservation needs a conditional write, transaction, or state-machine service. This is the design's core consistency pattern.
Regional scalability
Demand is local and bursty. Use regional routing so New York traffic lands in the New York market cluster.
Low latency
Rider request, driver offer, and location updates are interactive. Keep matching and location state close to the city being served.
Availability
If one city cluster degrades, it should not take down every market. Regional isolation matters.
#API Design
Request ride
POST /api/v1/rides
Request:
{
"pickup": { "lat": 40.741, "lng": -73.989 },
"destination": { "lat": 40.758, "lng": -73.985 },
"vehicleType": "standard"
}
Response:
{
"rideId": "ride_123",
"status": "matching",
"fareEstimateCents": 1840,
"etaSeconds": 240
}
Update driver location
POST /api/v1/drivers/driver_123/location
Accept ride offer
POST /api/v1/rides/ride_123/accept
The accept endpoint should validate the active driver reservation before changing ride state.
#High Level Design
Driver apps stream location updates into a regional location ingest service. The service updates a TTL-backed geo index used by matching.
Rider apps request rides through the gateway. The matching service queries nearby available drivers, asks pricing for fare and ETA context, reserves one driver in the ride state store, and sends an offer through a dispatch stream.
#Detailed Design
Location state
Latest location is ephemeral and high churn. Store it by driver id and geo cell with TTL. Durable trip history can be written asynchronously. This is closer to Presence and Ephemeral State than to a normal profile database.
Matching
The matching service:
- Finds candidates in nearby cells
- Computes ETA
- Ranks candidates
- Attempts an atomic driver reservation
- Sends offer
- Releases and retries on timeout
State consistency
Ride and driver state should be updated together. If the system uses separate stores, use a single assignment service to serialize the transition.
Regional topology
Partition by city or market. Keep rider requests, driver pings, matching, and active ride state in the same region. This is geo-partitioning applied to a fast-moving marketplace.
#Common Interview Mistakes
- Scanning all drivers to find the nearest one
- Writing every driver GPS ping to the primary SQL database
- Treating a nearby driver as assigned before reservation
- Ignoring driver offer timeouts
- Designing one global cluster for all cities
See also: Ride Matching and Dispatch, High-Write Location Tracking, Geospatial Indexing, and the Proximity Service solution.