For a full example answer with detailed architecture diagrams and deep dives, see our Design Uber guide.
Also review the Caching, Message Queues, and Databases building blocks for background on geospatial indexing, event streaming, and durable trip state management.
Design a ride-sharing service like Uber that allows users to request rides, matches them with nearby drivers, handles real-time tracking, and processes payments. Users request a ride, get matched to a driver in real time, watch the car approach on a map, take the trip, and pay seamlessly in-app.
The system must handle millions of concurrent users across multiple cities. The core challenges are maintaining a real-time index of driver locations that updates every few seconds, matching riders to nearby available drivers under contention (especially during surge periods), tracking the trip lifecycle with real-time map updates to the rider, and orchestrating a multi-step payment flow that handles holds, captures, tips, and driver payouts. Interviewers test your ability to decompose the product into services, choose the right data models for location queries, handle unreliable mobile networks, and reason about correctness with eventual consistency and idempotency.
Based on real interview experiences, these are the areas interviewers probe most deeply:
Finding the best available driver near a rider is the defining technical challenge. Interviewers want to see how you index driver locations, search efficiently, and handle contention when multiple riders compete for the same drivers.
Hints to consider:
Drivers continuously stream GPS coordinates while riders expect smooth map updates. This creates a high-throughput ingest problem with strict latency requirements.
Hints to consider:
A ride progresses through multiple states (requested, matched, driver-en-route, arrived, in-progress, completed) with transitions triggered by different actors. State management must survive server crashes and handle timeouts.
Hints to consider:
The payment flow spans authorization, hold, capture, tip addition, and driver payout, with external gateway calls that can fail at any point.
Hints to consider:
During peak demand, many riders compete for a small pool of drivers. Interviewers want to see how you maintain fairness and performance under extreme contention.
Hints to consider:
Confirm scope and constraints. Ask about the number of concurrent riders and drivers, whether the design covers a single city or multiple cities, and whether ride types (pool, shared, luxury) are in scope. Clarify whether driver matching should optimize for speed (nearest driver) or quality (best ETA considering traffic). Verify payment flow expectations: real-time capture or post-trip settlement. Establish latency targets for matching, location updates, and payment processing.
Sketch the core services: a Ride Service that manages ride requests and trip state machines in PostgreSQL, a Location Service that ingests driver GPS updates and maintains a real-time geospatial index in Redis, a Dispatch Service that matches riders to drivers using proximity queries and atomic reservations, a Tracking Service that pushes location updates to riders via WebSocket, a Payment Service that orchestrates authorization, capture, and payouts using the saga pattern, and a Notification Service for push alerts. Use Kafka as the event backbone connecting these services. Show two primary flows: the matching flow (ride request, geo query, driver reservation, acceptance) and the payment flow (authorization hold, trip completion, capture, payout).
Cover real-time tracking: after matching, the Tracking Service subscribes to the assigned driver's location stream in Kafka and pushes updates to the rider's WebSocket connection every 3-5 seconds. Discuss ETA recalculation using traffic APIs as the driver progresses. Address payment: authorization hold at match time, final capture at trip completion with the metered fare, tip addition within 24 hours as a separate charge. Cover monitoring: track matching latency per city, driver utilization rates, payment success rates, and trip cancellation reasons. Discuss disaster recovery: persist trip state in PostgreSQL with synchronous replication, use Kafka for event replay, and maintain fallback matching logic that degrades gracefully if Redis is temporarily unavailable. Mention fraud detection: flag rides with suspicious patterns (unusual route, repeated cancellations) for review.
"Asked about how to design Uber. How to avoid drivers getting multiple requests and how can a given ride only have one request sent."
"Design a ride sharing service. Make assumptions that you can use third-party APIs for already solved problems such as drivers near certain location coordinates."
Walk through the matching algorithm in detail. When a rider requests a ride, the Dispatch Service queries the Redis geospatial index for available drivers within a 2-mile radius of the pickup point. It filters by availability status and vehicle type, ranks candidates by a score combining proximity and estimated arrival time, then attempts to reserve the top candidate using Redis SETNX with a 30-second TTL. A push notification is sent to the driver's app. If the driver accepts, the trip transitions to "matched" and the reservation is converted to an active trip assignment. If the driver declines or times out, the reservation expires and the next candidate is tried. Discuss how concurrent ride requests for the same driver are handled: the SETNX ensures only one request wins the reservation; losers immediately move to the next candidate without waiting. Address the expansion strategy: if no drivers are found within 2 miles, progressively expand to 4, then 8 miles, with each expansion adding latency that is communicated to the rider.