System Design Interview: Design Uber
"Design Uber" is one of the most common system design prompts because it touches geospatial indexing, real-time location streaming, matching, and high write throughput all at once. The interviewer isn't looking for the real Uber architecture — they want to see you scope the problem, make defensible choices, and reason about scale out loud.
Work it in a deliberate order: clarify requirements, estimate scale, sketch the core entities and APIs, design the data and the matching path, then talk through bottlenecks and trade-offs. The walk-through below follows that order so you can practice the structure, not just the answer.
1. Clarify requirements
Separate functional from non-functional, and pin scope before designing. Riders request a ride and see a driver approach in real time; drivers go online and receive nearby requests; the system matches them and tracks the trip to completion.
- Functional: request a ride, match to a nearby driver, live-track the trip, fare calculation, trip history.
- Non-functional: low-latency matching (seconds), high availability, real-time location updates, consistency of a driver being assigned to exactly one rider.
- Out of scope (say so): payments processing internals, ratings, surge ML — mention them, then defer.
2. Estimate scale
Back-of-envelope numbers justify later choices. Assume ~10M daily active drivers sending a location ping every 4 seconds — that's ~2.5M writes/second of location data, a write-heavy workload that immediately rules out a naive relational table as the hot path.
3. Core components and APIs
Sketch the services and the request flow. Keep the matching path independent from the durable trip store so each can scale on its own characteristics.
- Location service: ingests driver pings, keeps current positions in an in-memory geospatial index.
- Matching service: on a ride request, queries nearby online drivers and assigns one.
- Trip service: durable record of trip lifecycle (requested → matched → ongoing → completed).
- Notification/streaming: pushes live driver position to the rider (WebSocket/long-poll).
4. Geospatial matching — the heart of the problem
This is what the interviewer most wants to hear. Storing raw lat/long and scanning is O(n); you need a spatial index. Explain quadtrees or geohashing: divide the map into cells so 'find drivers near this point' becomes a lookup of a few cells, not a full scan.
Geohashing encodes a region into a short string where shared prefixes mean spatial proximity, which makes 'nearby' a prefix query. Drivers' current cells live in an in-memory store (e.g. Redis) for fast reads and frequent updates; cell granularity is a tunable trade-off between precision and fan-out.
5. Scaling and bottlenecks
Name the pressure points and how you'd relieve them. The 2.5M writes/second location stream is the dominant one.
- Shard the location index geographically — a city's drivers and riders are handled by the same shard, keeping matching local.
- Absorb the write spike with an in-memory store and async durable writes; you don't need every ping in a durable DB.
- Ensure one-driver-one-rider with an atomic assignment (a lock or conditional update) to avoid double-booking.
- Use a message queue (Kafka) between location ingestion and downstream consumers to decouple spikes.
6. Trade-offs to verbalize
Close by naming the tensions an interviewer rewards: strong vs eventual consistency (driver assignment must be strong; location display can be eventual), in-memory speed vs durability, and cell-size precision vs query fan-out. Stating these explicitly is the difference between a passing and a strong answer.
Practice Uber system design with real-time help
Natively's system design interview assistant can keep you structured during a live round — suggesting the next dimension to cover and surfacing trade-offs in real time, all on your own device.
Ready to try Natively?
Download the definitive local AI interview assistant today and ace your next coding interview with complete privacy.
Get Started Free