Uber System Design — Complete Guide
A beginner-friendly, end-to-end system design document
Table of Contents
1. Customer User Journeys
2. Functional Requirements
3. Non-Functional Requirements
4. Estimations & Constraints (Capacity Planning)
5. Tech Concepts Behind Uber's System Design
6. Overall System Design & Summary
7. APIs (Beginner Friendly)
8. How to Use This to Build Your Own App
1. Customer User Journeys
Understanding the real flow of a product is the foundation of good system design. Uber has two
primary actors: Rider and Driver. Let's walk through both.
1.1 Rider Journey (Book a Ride)
1. Open App → App fetches rider's current GPS location.
2. Enter Destination → App shows estimated fare, ETA, and ride types (UberX, UberXL,
Premier).
3. Confirm Pickup Location → Rider can drag pin to adjust exact pickup point.
4. Request Ride → Request is sent to the Matching Service.
5. Driver Matching → System finds nearest available drivers, sends request to one (or
sequentially to a few).
6. Driver Accepts → Rider sees driver's name, photo, car details, plate number, and live
location moving toward pickup.
7. Live Tracking → Rider tracks driver's car on map in real time (via GPS pings every few
seconds).
8. Ride Starts → Driver marks "Trip Started" when rider boards.
9. Live Trip Tracking → Route, ETA to destination shown.
10. Ride Ends → Driver marks "Trip Completed."
11. Payment → Fare auto-charged to saved payment method (card/wallet).
12. Rating & Feedback → Rider rates driver (1–5 stars), optional tip and comments.
13. Receipt → Trip summary emailed/shown in-app.
1.2 Driver Journey
1. Go Online → Driver toggles "Available" status; location starts streaming to server.
2. Receive Ride Request → Gets push notification with pickup location, estimated earnings,
rider rating.
3. Accept/Reject → Driver has ~10-15 seconds to respond.
4. Navigate to Pickup → In-app navigation (or hands off to Google Maps).
5. Start Trip → Confirms rider via OTP/QR or just clicks "Start."
6. Navigate to Destination → Turn-by-turn navigation.
7. End Trip → Fare calculated automatically.
8. Receive Payment → Added to driver's wallet/weekly payout.
9. Rate Rider → Mutual rating system.
1.3 Edge-Case Journeys (Important for design!)
• Cancellation — by rider before/after match, by driver before pickup.
• No drivers available — surge pricing or "no cars found" message.
• Driver doesn't show up — auto-cancellation + re-matching + refund logic.
• Network drop mid-ride — offline mode caches GPS, syncs later.
• Multiple stops — rider adds intermediate destination mid-trip.
• Scheduled rides — booked in advance (e.g., airport pickup tomorrow 6 AM).
2. Functional Requirements
These define what the system must do.
# Requirement Description
1 Rider Registration/Login Sign up via phone/email/social,
OTP verification
2 Driver Registration KYC, vehicle documents,
background check
3 Real-time Location Tracking Both rider & driver GPS
broadcast continuously
4 Ride Matching Match nearest available driver
to rider request
5 Fare Estimation Calculate estimated fare before
booking
6 Dynamic/Surge Pricing Adjust price based on demand-
supply ratio
# Requirement Description
7 Trip Management Start, track, end, cancel trips
8 Routing/ETA Shortest path + live ETA using
maps service
9 Payments Card, wallet, cash, UPI; auto-
charge on trip end
10 Ratings & Reviews Both rider and driver rate each
other
11 Notifications Push/SMS for ride status
updates
12 Trip History Past rides, receipts, invoices
13 Driver Earnings Dashboard Daily/weekly earnings,
incentives
14 Support/Helpdesk In-app chat/call, dispute
resolution, SOS/safety button
15 Promotions/Coupons Discount codes, referral system
16 Scheduled Rides Book in advance
17 Multiple Ride Types UberX, Pool, XL, Premier,
Auto, etc.
3. Non-Functional Requirements
These define how well the system performs — usually the harder, more interesting part of system
design interviews.
Requirement Why It Matters Target
High Availability Riders/drivers must always be 99.99% uptime
able to use the app
Low Latency Matching and location updates < 100ms for location updates, <
must feel instant 2s for matching
Scalability Must handle millions of Horizontally scalable
concurrent users globally microservices
Consistency vs Availability Trip state matters more than Eventual consistency for
perfect global consistency location; strong consistency for
payments/trip state
Fault Tolerance A server crash shouldn't cancel Replication, failover, retries
active trips
Geographic Distribution Uber operates in 70+ countries Multi-region deployment, data
locality
Security Protect payment info, personal Encryption (TLS, AES),
data, location tokenized payments
Durability Trip & payment records must Persistent storage with
Requirement Why It Matters Target
never be lost replication
Real-Time Processing GPS pings, surge calculation Stream processing (Kafka,
Flink)
Key System Design Insight: Uber is a textbook example of the CAP theorem
trade-off — location data favors Availability + Partition tolerance (AP), while
payment/billing favors Consistency (CP).
4. Estimations & Constraints (Capacity Planning)
This is where you show interviewers (and yourself) that you can think quantitatively.
4.1 Assumptions
• Total Users: 100 million monthly active users (riders)
• Active Drivers: 5 million
• Daily Rides: ~15 million trips/day
• Peak concurrency: 500,000 concurrent active rides during peak hours
4.2 Location Update Load
• Each driver sends GPS ping every 4 seconds while online.
• Online drivers at peak: ~2 million
• Pings/sec = 2,000,000 / 4 = 500,000 location updates/sec
4.3 Storage Estimation
• Each trip record ≈ 1 KB (metadata) + GPS trail ≈ 50 KB
• Daily trips: 15 million × 51 KB ≈ 765 GB/day
• Yearly: ~280 TB/year (before replication/compression)
4.4 Matching Service Load
• Ride requests/sec at peak ≈ 500,000 rides/day ÷ (4 peak hours × 3600s) ≈ ~35 requests/sec
per major city; aggregated globally could be in the thousands/sec.
4.5 Bandwidth
• 500,000 location pings/sec × ~200 bytes/ping ≈ 100 MB/sec of location traffic alone.
4.6 Constraints to Keep in Mind
• Must work in areas with poor connectivity (offline caching of GPS).
• Must support multiple cities/regions with independent surge pricing.
• Driver and rider apps must be battery efficient (GPS drains battery fast).
• Must comply with regional regulations (data residency, taxi laws).
5. Tech Concepts Behind Uber's System Design
This section explains the building blocks — concepts every student should master.
5.1 Geospatial Indexing (The Heart of Uber)
Uber needs to answer: "Which drivers are near this rider?" — fast, for millions of points.
• Naive approach: Compare rider's lat/long with every driver → O(n), too slow.
• Solution: Geohashing / Quadtrees / Google's S2 Geometry / Uber's own H3 library
• These divide the map into hexagonal or square cells.
• Each driver's location maps to a cell ID (a string like 9q8yyk).
• To find nearby drivers, just look up drivers in the same/nearby cells — O(1) or O(log
n).
• Uber actually built H3 (hexagonal hierarchical spatial index) for exactly this
purpose.
5.2 Real-Time Communication
• Drivers' location updates use WebSockets or long-polling/MQTT (lightweight pub-sub)
instead of constant HTTP requests — reduces overhead.
• Apache Kafka ingests millions of location pings/sec as a durable, ordered event stream.
5.3 Microservices Architecture
Uber doesn't run as one giant app — it's broken into independently deployable services:
• Rider Service, Driver Service, Trip Service, Matching Service, Pricing Service, Payment
Service, Notification Service, Maps/ETA Service.
• Each can scale independently (e.g., Matching Service scales more during rush hour).
5.4 Load Balancing
• API Gateway + Load Balancers (e.g., NGINX, Envoy) distribute incoming requests across
service instances to avoid overload on one server.
5.5 Caching
• Redis caches frequently accessed data — e.g., driver locations, surge multipliers — for sub-
millisecond reads instead of hitting the database every time.
5.6 Databases — Polyglot Persistence
Uber uses different databases for different needs (a key system design lesson — "no one-size-
fits-all DB"):
• Cassandra/DynamoDB — for high-write trip & location data (NoSQL, horizontally
scalable).
• PostgreSQL/MySQL — for transactional data like payments, user accounts (needs ACID).
• Redis — caching, leaderboard-style "nearest driver" lookups.
• Elasticsearch — search, support ticket lookup.
5.7 Message Queues / Event Streaming
• Kafka decouples services — e.g., when a trip ends, an event is published; Payment Service,
Rating Service, and Analytics Service all consume it independently without tight coupling.
5.8 Matching Algorithm
• A simplified version: find drivers within a radius (using geospatial index) → rank by
distance, ETA, rating → send request → first to accept wins.
• Real Uber uses ML models considering driver acceptance rate, traffic, and even longer-term
marketplace efficiency (not just nearest driver).
5.9 Surge Pricing
• Real-time supply/demand ratio per geo-cell is computed continuously (open ride requests vs
available drivers in that hexagon).
• Pricing Service applies a multiplier when demand > supply.
5.10 Maps & Routing
• Uses map-matching algorithms (snapping noisy GPS points to actual roads) and routing
engines (Dijkstra/A* algorithms, or more advanced contraction hierarchies) for ETA &
turn-by-turn navigation. Often built on OpenStreetMap data + their own routing engine.
5.11 Consistency Models
• Trip state machine (Requested → Accepted → Ongoing → Completed → Paid) needs
strong consistency — you can't have two drivers both think they're assigned to the same
rider.
• Location updates can be eventually consistent — a 1-second-old driver position is fine.
5.12 Fault Tolerance & Replication
• Data replicated across multiple data centers/availability zones.
• Circuit breakers prevent one failing microservice from cascading failure across the system.
6. Overall System Design & Summary
6.1 High-Level Architecture (described, since this is a text doc)
┌─────────────────────┐
│ Mobile Apps │
│ (Rider App / Driver) │
└──────────┬────────────┘
│ HTTPS / WebSocket
┌──────────▼────────────┐
│ API Gateway │
│ (Auth, Rate Limiting, │
│ Load Balancing) │
└──────────┬────────────┘
┌─────────────────────┼─────────────────────┐
│ │ │
┌────────▼───────┐ ┌─────────▼────────┐ ┌─────────▼─────────┐
│ Rider Service │ │ Driver Service │ │ Trip Service │
└────────┬───────┘ └─────────┬────────┘ └─────────┬─────────┘
│ │ │
┌────────▼─────────────────────▼───────────────────────▼─────────┐
│ Matching / Dispatch Service │
│ (uses Geospatial Index — H3/Geohash — to find drivers) │
└────────┬─────────────────────┬───────────────────────┬─────────┘
│ │ │
┌────────▼───────┐ ┌─────────▼────────┐ ┌─────────▼─────────┐
│ Pricing Service │ │ Maps/ETA Service │ │ Payment Service │
│ (Surge Pricing) │ │ (Routing engine) │ │ (Wallet/Card/UPI) │
└─────────────────┘ └────────────────────┘ └────────────────────┘
│ │ │
┌────────▼─────────────────────▼───────────────────────▼─────────┐
│ Kafka (Event Streaming Backbone) │
└────────┬─────────────────────┬───────────────────────┬─────────┘
│ │ │
┌────────▼───────┐ ┌─────────▼────────┐ ┌─────────▼─────────┐
│ Notification │ │ Analytics/ML │ │ Rating/Feedback │
│ Service (Push/ │ │ Service (Surge │ │ Service │
│ SMS) │ │ Prediction, Fraud)│ │ │
└─────────────────┘ └────────────────────┘ └────────────────────┘
Storage Layer: Cassandra (trips/locations) | PostgreSQL (users/payments)
Redis (cache) | Elasticsearch (search/support)
6.2 Flow Summary
1. Rider/Driver apps talk to backend via API Gateway.
2. Driver location continuously streams through WebSocket → Kafka → Location Service
(stored in Redis for fast lookup + Cassandra for history).
3. Rider requests a ride → Matching Service queries nearby drivers using geospatial index
(H3).
4. Pricing Service computes fare (with surge if applicable).
5. Once matched, Trip Service manages the trip's state machine.
6. Maps Service provides routing/ETA throughout.
7. On completion, Payment Service charges the rider and credits the driver.
8. Notification Service sends real-time updates to both parties.
9. All events flow through Kafka so other services (analytics, fraud detection, ratings) can
react independently.
6.3 Why This Design Works
• Decoupled microservices → independent scaling & deployment.
• Geospatial indexing → fast nearest-driver lookup at massive scale.
• Event-driven architecture (Kafka) → resilience and loose coupling.
• Polyglot persistence → right database for the right job.
• Caching (Redis) → handles read-heavy, latency-sensitive operations.
7. APIs (Beginner-Friendly)
Here are simplified REST API examples you could actually implement in a student project.
7.1 Authentication
POST /api/v1/auth/register
Body: { "phone": "+919999999999", "name": "John", "role": "rider" }
Response: { "userId": "u123", "otpSent": true }
POST /api/v1/auth/verify-otp
Body: { "userId": "u123", "otp": "4521" }
Response: { "token": "jwt_token_here" }
7.2 Location Update (Driver)
POST /api/v1/driver/location
Headers: Authorization: Bearer <token>
Body: { "lat": 17.4239, "lng": 78.4738, "timestamp": 1719234000 }
Response: { "status": "updated" }
7.3 Estimate Fare
GET
/api/v1/fare/estimate?pickupLat=17.42&pickupLng=78.47&dropLat=17.40&dropLng=78.5
0&rideType=UberX
Response: {
"estimatedFare": 220,
"currency": "INR",
"eta": "5 mins",
"surgeMultiplier": 1.2
}
7.4 Request a Ride
POST /api/v1/rides/request
Body: {
"riderId": "r456",
"pickup": { "lat": 17.4239, "lng": 78.4738 },
"drop": { "lat": 17.4065, "lng": 78.4772 },
"rideType": "UberX"
}
Response: { "rideId": "ride_789", "status": "SEARCHING_DRIVER" }
7.5 Driver Accepts Ride
POST /api/v1/rides/{rideId}/accept
Body: { "driverId": "d321" }
Response: { "status": "ACCEPTED", "driverETA": "3 mins" }
7.6 Get Ride Status (Polling or via WebSocket)
GET /api/v1/rides/{rideId}/status
Response: {
"status": "ONGOING",
"driverLocation": { "lat": 17.415, "lng": 78.460 },
"etaToDestination": "8 mins"
}
7.7 End Trip
POST /api/v1/rides/{rideId}/end
Response: {
"status": "COMPLETED",
"finalFare": 245,
"distance": "6.2 km",
"duration": "18 mins"
}
7.8 Make Payment
POST /api/v1/payments/charge
Body: { "rideId": "ride_789", "amount": 245, "method": "card" }
Response: { "paymentStatus": "SUCCESS", "transactionId": "txn_001" }
7.9 Rate Trip
POST /api/v1/rides/{rideId}/rate
Body: { "ratedBy": "rider", "rating": 5, "comment": "Great driver!" }
Response: { "status": "saved" }
7.10 WebSocket Events (Real-Time Updates)
[Link]
Server → Client events:
{ "event": "DRIVER_LOCATION_UPDATE", "lat": 17.41, "lng": 78.46 }
{ "event": "RIDE_STATUS_CHANGED", "status": "ARRIVED" }
{ "event": "TRIP_ENDED", "fare": 245 }
8. How to Use This to Build Your Own App
Suggested Learning Path (Build a Mini-Uber Clone)
1. Start small: Build Auth + basic Rider/Driver CRUD APIs ([Link]/Express or Spring
Boot).
2. Add location tracking: Use a simple lat/lng update endpoint, store in Redis or even just in-
memory for v1.
3. Implement basic matching: Start with brute-force nearest driver (loop through all drivers)
— then upgrade to geohashing once you understand the bottleneck.
4. Add a simple state machine for trip status (REQUESTED → ACCEPTED → ONGOING
→ COMPLETED).
5. Integrate a map SDK (Google Maps / Mapbox) for visualization and routing.
6. Add a mock payment flow (don't need real payment gateway for learning — simulate it).
7. Add WebSockets for real-time location updates instead of polling.
8. Scale up conceptually: Once it works for 10 users, ask "what breaks at 10,000 users?" —
that's when you introduce Kafka, load balancers, and caching.
Key Takeaways for System Design Interviews
• Always start with clarifying requirements (functional + non-functional) before jumping to
design.
• Do back-of-envelope estimation — interviewers love seeing you reason about scale.
• Know at least one geospatial indexing technique (geohash/quadtree/H3) — it's the single
most asked deep-dive in ride-sharing system design.
• Understand trade-offs: consistency vs availability, SQL vs NoSQL, push vs pull for real-
time updates.
• Practice drawing the high-level architecture diagram from memory — that's the most tested
skill.
Summary
Uber's system design teaches the most important real-world concepts in distributed systems:
• Geospatial indexing for fast nearest-neighbor search at scale
• Event-driven microservices for resilience and independent scaling
• Polyglot persistence — choosing the right database for the right job
• Real-time communication via WebSockets and streaming pipelines (Kafka)
• CAP theorem trade-offs applied to a real product (location vs payment consistency)
Master these concepts using this document as a reference, build the mini-clone described in Section
8, and you'll have hands-on understanding of one of the most commonly asked system design
problems in interviews — and a genuinely useful foundation for building real location-based apps.
Document prepared as a complete learning resource for system design students.