How would you design an app like Uber?
Uber connects a rider who needs to get somewhere with a driver who's nearby. Simple concept. The system behind it handles millions of location updates per...
30 Mar 2024

Uber connects a rider who needs to get somewhere with a driver who's nearby. Simple concept. The system behind it handles millions of location updates per second, real-time matching algorithms, dynamic pricing, payment processing, and navigation — all while both parties are moving.
The hardest part of designing Uber isn't the ride request. It's the matching: finding the right driver for the right rider in real-time, accounting for location, traffic, driver availability, and surge pricing. That's a geospatial, real-time optimization problem at massive scale.
Non-Technical Requirements
- Scalability — millions of concurrent ride requests across hundreds of cities. Each city has different traffic patterns, peak hours, and driver supply.
- Reliability — a failed ride request means a stranded passenger. The system must be highly available with minimal downtime.
- Availability — 24/7 service globally. New Year's Eve, airport rushes, concert endings — the system must handle unpredictable traffic spikes.
- Safety and Security — background checks for drivers, ride tracking for passengers, emergency features, and payment security.
- User Experience — request a ride in two taps. See the driver on a map. Know the price before confirming. Get a receipt automatically.
Technical Requirements
- Real-Time Location Processing — drivers send location updates every 3-4 seconds. That's millions of location pings per second globally. The system must ingest, process, and index these in near-real-time.
- Geospatial Matching — when a rider requests a ride, the system must find available drivers nearby, estimate arrival time for each, and select the optimal match. This requires geospatial indexes (geohash, quadtree, or H3) and efficient proximity queries.
- High Availability — redundant components, load balancers, failover mechanisms. Uber uses multiple data centers with active-active architecture.
- Scalable Infrastructure — horizontal scaling for stateless services. Geo-partitioned databases. Regional deployments.
- Microservices Architecture — Uber famously migrated from a monolith to microservices. Each domain (matching, pricing, payments, navigation, notifications) is an independent service.
Database Strategy
This is a fascinating part of Uber's evolution:
Uber started with PostgreSQL. Scalability issues forced them to diversify. They built Schemaless, a custom distributed datastore on top of MySQL, for long-term storage. They use Riak and Cassandra for high-availability, low-latency workloads. Redis handles caching and queueing (some behind Twemproxy for scalable caching). They're also building their own distributed column store orchestrating MySQL instances.
The lesson: no single database fits all of Uber's needs. Different data (location pings, trip records, payment history, user profiles) has different access patterns and different requirements for consistency, latency, and throughput.
The Matching Problem
When a rider requests a ride:
- The system queries the geospatial index for available drivers within a radius.
- For each candidate driver, it estimates arrival time (considering current location, heading, and traffic).
- It applies business rules: driver rating, vehicle type match, driver preferences.
- It selects the best match and sends the request to the driver.
- If the driver declines or doesn't respond within 15 seconds, the system tries the next best match.
The geospatial index must handle constant updates (drivers are moving) and fast reads (rider requests need sub-second matching). Geohashing is the common approach: divide the world into grid cells. Drivers are indexed by their current geohash. Finding nearby drivers means querying adjacent geohash cells.
The trade-off: smaller cells give more precise proximity but require checking more cells. Larger cells are faster to query but include more distant drivers. Uber uses a hierarchical approach — multiple resolution levels.
Surge Pricing
When demand exceeds supply in an area, prices go up. This is both an economic mechanism (incentivize more drivers to that area) and a system design challenge:
- Divide each city into zones.
- Track real-time supply (available drivers) and demand (ride requests) per zone.
- Calculate a multiplier based on the supply/demand ratio.
- Apply the multiplier to the base fare.
- Update the multiplier every few minutes.
The trade-off: surge pricing balances supply and demand efficiently but frustrates riders. Uber shows the multiplier upfront and requires confirmation for high surges. Transparency reduces frustration but doesn't eliminate it.
The Trade-Offs
Precision vs. speed in matching. Finding the globally optimal driver-rider match across an entire city is computationally expensive. Finding a good-enough local match is fast. Uber optimizes locally (within a radius) and it works well enough.
Consistency vs. availability for location data. Driver locations are ephemeral — they change every few seconds. Eventual consistency is fine here. But trip data (ride started, payment processed) needs stronger consistency. Different consistency models for different data types.
Monolith vs. microservices. Uber's monolith worked for one city. It couldn't work for hundreds of cities with different regulations, currencies, and driver types. Microservices enabled independent team velocity but added massive operational complexity.
Real-time vs. batch for analytics. Uber needs real-time analytics for surge pricing and driver dispatch. But historical analytics (revenue reports, driver earnings, city performance) can be batch-processed. Two different data pipelines for two different needs.
Uber's system design is a masterclass in handling real-time geospatial data at scale. The key takeaway: the simpler the user experience (two taps to request a ride), the more complex the system behind it.
Keep reading
- The Capacity Estimation Numbers Every Engineer Should Carry Into a System Design
- Notes From My First Cohort: System Design Is Trade-offs, Not Answers
- Write HLDs and ADRs in HTML or React, Not Markdown
- CRDTs: Conflict-Free Merging in Distributed Systems
- Race Conditions: What They Are and How to Handle Them
- SLO, SLA, SLI: What They Actually Mean and How to Use Them