Ride Sharing System Design: A Complete Architecture Guide
Designing a ride-sharing platform like Uber or Lyft is one of the most popular system design interview questions — and for good reason. It touches on real-time communication, geospatial indexing, dynamic pricing, and high-throughput distributed systems. In this guide, we break down a complete ride sharing system design from requirements to scale estimation.
Functional Requirements#
Before diving into architecture, clarify what the system must do:
- Riders can request a ride by specifying pickup and drop-off locations.
- Drivers can go online/offline and accept or decline ride requests.
- The system matches a rider with the best available driver.
- Both parties see real-time location updates during the trip.
- The system calculates fare estimates before the ride and final charges after.
- Payment is processed automatically at the end of the trip.
- Trip history is stored for both riders and drivers.
Non-Functional Requirements#
- Low latency matching — a rider should be matched within seconds.
- High availability — the system must be up 99.99% of the time.
- Consistency — a driver must not be assigned to two riders simultaneously.
- Scalability — support millions of concurrent users across cities.
Scale Estimation#
Assume 50 million monthly active riders, 5 million drivers, and 20 million rides per day.
- Rides QPS: 20M / 86400 ≈ ~230 rides/sec, peak ~1000 rides/sec.
- Location updates: If 2M drivers are online sending updates every 3 seconds, that is ~670K writes/sec — a significant ingestion rate.
- Storage: Each ride record ~1 KB → 20M × 1 KB = 20 GB/day, ~7 TB/year. Location history is much larger — budget for 50+ TB/year.
High-Level Architecture#
The system decomposes into several services:
- Rider Service — handles ride requests, fare estimates, trip history.
- Driver Service — manages driver availability, location ingestion.
- Matching Service — pairs riders with drivers.
- Pricing Service — computes fare estimates and surge pricing.
- Trip Service — manages the trip lifecycle from start to completion.
- Payment Service — charges riders and pays drivers.
- Notification Service — pushes real-time updates via WebSockets.
An API Gateway sits in front of all services, handling authentication, rate limiting, and routing.
Location Tracking#
GPS Ingestion#
Drivers continuously send GPS coordinates (latitude, longitude, timestamp, heading, speed). These are ingested through a high-throughput pipeline — think Kafka or Amazon Kinesis — that can handle hundreds of thousands of writes per second.
Geohashing#
Storing and querying raw lat/lng pairs is expensive. Geohashing converts a 2D coordinate into a 1D string, enabling prefix-based proximity searches. A geohash of precision 6 (~1.2 km × 0.6 km) is a good starting resolution for finding nearby drivers.
The Driver Location Index is an in-memory store (Redis or a custom solution) mapping geohash cells to sets of active driver IDs. When a rider requests a ride, the system queries the rider's geohash cell and its neighbors.
Quadtrees#
An alternative to geohashing is a quadtree, which recursively divides the map into four quadrants. Quadtrees adapt to driver density — dense city areas get finer subdivisions, rural areas stay coarse.
Matching Algorithm#
Matching is the core of the system. When a ride request arrives:
- Find nearby drivers — query the geohash index for drivers within a radius (e.g., 3 km).
- Filter — remove drivers who are already on a trip or have a low rating.
- Rank by ETA — call a routing/ETA service (or use a precomputed ETA matrix) to estimate how long each candidate driver would take to reach the pickup.
- Select the best — pick the driver with the lowest ETA (or use a scoring function that also factors in driver rating, vehicle type, acceptance rate).
- Offer the ride — send a push notification to the selected driver with a timeout (e.g., 15 seconds). If declined or timed out, move to the next candidate.
To prevent double-assignment, the matching service acquires a distributed lock on the driver before offering the ride.
Pricing and Surge#
Base Fare Calculation#
fare = base_fare + (cost_per_km × distance) + (cost_per_min × duration) + booking_fee
The Pricing Service uses the routing engine to estimate distance and duration for the fare estimate shown to the rider before confirming.
Dynamic / Surge Pricing#
When demand outstrips supply in a geographic zone, surge pricing kicks in. The system monitors the ratio of open requests to available drivers per geohash region. When the ratio crosses a threshold, a surge multiplier (e.g., 1.5×, 2.0×) is applied.
Surge pricing is recalculated every few minutes. The multiplier is stored per zone and applied at fare estimation time.
Trip Lifecycle#
A ride progresses through defined states:
- REQUESTED — rider submits a ride request.
- MATCHING — system searches for a driver.
- DRIVER_ASSIGNED — a driver accepts.
- EN_ROUTE_TO_PICKUP — driver is heading to the rider.
- ARRIVED — driver arrives at the pickup location.
- IN_PROGRESS — trip is underway.
- COMPLETED — rider is dropped off; fare is finalized.
- CANCELLED — either party cancels (cancellation fees may apply).
A state machine ensures valid transitions. Each state change is written to an event log (Kafka) for downstream consumers — billing, analytics, fraud detection.
Real-Time Location Updates#
During a trip, both rider and driver need live location on their maps. The driver app streams GPS to the backend, which relays it to the rider via WebSocket connections.
A dedicated Location Streaming Service manages WebSocket connections. It subscribes to the driver's location topic on Kafka and pushes updates to the connected rider client. This keeps HTTP services stateless while the streaming layer handles persistent connections.
Driver and Rider Apps#
- Driver app: Background GPS tracking, ride offer notifications, navigation integration, earnings dashboard.
- Rider app: Pickup/drop-off selection on a map, fare estimate, live tracking, payment method management, ride history, ratings.
Both apps communicate with the backend via REST/gRPC for transactional calls and WebSockets for real-time streams.
Payment Integration#
After trip completion:
- The Trip Service emits a TRIP_COMPLETED event with the final fare.
- The Payment Service captures the pre-authorized amount (or charges the rider's payment method).
- The driver's earnings are credited to their wallet (settled on a weekly payout cycle).
Use a payment gateway (Stripe, Braintree) for PCI compliance. Implement idempotency keys to prevent double charges on retries.
Data Storage#
| Data | Store | Reason |
|---|---|---|
| User profiles, trip records | PostgreSQL | Relational, ACID transactions |
| Driver location index | Redis / custom in-memory | Ultra-low latency reads |
| Location history | Cassandra or S3 + Parquet | Append-heavy, time-series |
| Event log | Kafka | High-throughput streaming |
| Analytics | ClickHouse / BigQuery | OLAP queries on ride data |
Scaling Considerations#
- Shard the location index by city/region so that each city's driver pool is independent.
- Horizontally scale the matching service — partition by geography.
- Use connection load balancers for WebSocket servers.
- Cache surge multipliers and fare configs at the edge.
- Employ circuit breakers between services to prevent cascading failures.
Summary#
A ride-sharing system design revolves around real-time geospatial data, fast matching, dynamic pricing, and reliable trip state management. The key challenges are ingesting and querying driver locations at scale, matching riders to drivers with minimal latency, and maintaining consistency so no driver is double-booked.
Want to practice system design questions like this with an AI-powered mock interviewer? Try codelit.io — your all-in-one platform for coding and system design interview prep.
This is article #185 in our engineering blog series.
Try it on Codelit
Chaos Mode
Simulate node failures and watch cascading impact across your architecture
Related articles
Try these templates
Simple Ride-Sharing MVP
A basic ride-sharing app with core components for rider-driver matching.
5 componentsUber Real-Time Location System
Handles 5M+ GPS pings per second using H3 hexagonal geospatial indexing.
6 componentsInstagram-like Photo Sharing Platform
Full-stack social media platform with image processing, feeds, and real-time notifications.
12 componentsBuild this architecture
Generate an interactive Ride Sharing System Design in seconds.
Try it in Codelit →
Comments