Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.

← System Design Interview Playbook

Interview Framework

  • The 6-Step Design Framework
  • HLD Fundamentals Refresher
  • Requirement Gathering Practice
  • Domain Decomposition
  • API Contract Design
  • Data Ownership Model
  • Failure Scenario Walkthroughs
  • Architecture Diagramming
  • Back-of-Envelope Estimation

10 Case Studies

  • Design a URL Shortener
  • Design Twitter / X
  • Design WhatsApp
  • Design Netflix
  • Design a Rate Limiter
  • Design a Search Autocomplete
  • Design a Distributed Cache
  • Design a Notification Service
  • Design Uber / Ride Sharing
  • Design a Distributed File Storage System
  • Design a Distributed Task Scheduler
  • Design a Message Queue System
  • Design an Authentication System at Scale
  • Design a Distributed Logging & Metrics Pipeline
  • Design a Food Delivery Platform
  • Design a Real-Time Analytics Dashboard
  • Design a Monitoring & Alerting System
  • Design Container Orchestration Basics
  • Design a CI/CD Pipeline System
  • Design Service Mesh Basics
  • Design a Centralized Configuration & Secrets System
  • Design a Batch Processing System
  • Design a Data Warehouse / Analytics Storage Layer
  • Design Global Content Delivery
  • Case studies

    🏗️Design a URL Shortener
  • 🏗️Design a Rate Limiter
  • 🏗️Design Twitter / X
  • 🏗️Design WhatsApp
  • 🏗️Design Netflix
  • 🏗️Design a Distributed Cache
  • 🏗️Design a Notification Service
  • 🏗️Design a Search Autocomplete System
  • 🏗️Design Uber / Ride Sharing
  • 🏗️Design a Web Crawler
  • 🏗️Design a Payment System
  • 🏗️Design a Distributed Lock Service
  • 🏗️Design a Video Streaming Platform
  • 🏗️Design a Search Engine
  • 🏗️Design E-Commerce Checkout & Inventory at Scale
Chaturmind
← System Design Interview Playbook

Interview Framework

  • The 6-Step Design Framework
  • HLD Fundamentals Refresher
  • Requirement Gathering Practice
  • Domain Decomposition
  • API Contract Design
  • Data Ownership Model
  • Failure Scenario Walkthroughs
  • Architecture Diagramming
  • Back-of-Envelope Estimation

10 Case Studies

  • Design a URL Shortener
  • Design Twitter / X
  • Design WhatsApp
  • Design Netflix
  • Design a Rate Limiter
  • Design a Search Autocomplete
  • Design a Distributed Cache
  • Design a Notification Service
  • Design Uber / Ride Sharing
  • Design a Distributed File Storage System
  • Design a Distributed Task Scheduler
  • Design a Message Queue System
  • Design an Authentication System at Scale
  • Design a Distributed Logging & Metrics Pipeline
  • Design a Food Delivery Platform
  • Design a Real-Time Analytics Dashboard
  • Design a Monitoring & Alerting System
  • Design Container Orchestration Basics
  • Design a CI/CD Pipeline System
  • Design Service Mesh Basics
  • Design a Centralized Configuration & Secrets System
  • Design a Batch Processing System
  • Design a Data Warehouse / Analytics Storage Layer
  • Design Global Content Delivery
  • Case studies

    🏗️Design a URL Shortener
  • 🏗️Design a Rate Limiter
  • 🏗️Design Twitter / X
  • 🏗️Design WhatsApp
  • 🏗️Design Netflix
  • 🏗️Design a Distributed Cache
  • 🏗️Design a Notification Service
  • 🏗️Design a Search Autocomplete System
  • 🏗️Design Uber / Ride Sharing
  • 🏗️Design a Web Crawler
  • 🏗️Design a Payment System
  • 🏗️Design a Distributed Lock Service
  • 🏗️Design a Video Streaming Platform
  • 🏗️Design a Search Engine
  • 🏗️Design E-Commerce Checkout & Inventory at Scale
HomeLearnSystem Design Interview Playbook10 Case Studies
Uber / Ride Sharing

Design Uber / Ride Sharing

geospatialreal-timematchinglocation-tracking

Problem Statement

Design a ride-sharing platform like Uber. Riders request rides, drivers accept, and the system matches them in real time. Track driver location, display ETA, and handle surge pricing.

Requirements

Functional

  • ✓Riders can request a ride from location A to B
  • ✓System matches rider with nearby available driver
  • ✓Real-time driver location tracking on rider's map
  • ✓ETA calculation
  • ✓Surge pricing based on demand
  • ✓Trip history and payment

Non-Functional

  • ✓1M concurrent rides globally
  • ✓Driver location updates every 5 seconds
  • ✓Match rider to driver within 5 seconds
  • ✓Geospatial queries at scale

Capacity Estimation

Capacity Estimation

  • Active drivers: 5M worldwide, 1M online at peak
  • Location updates: 1M drivers × 1 update/5s = 200K location writes/sec
  • Ride requests: 1M concurrent rides → ~200K new requests/hour
  • Geospatial index size: 1M driver locations × 64 bytes = ~64 MB — fits in Redis

High-Level Architecture

Architecture

[Driver App]
  → location update every 5s
  → [Location Service]
        → Redis Geo (GeoHash index)
        → Kafka (location events for analytics)

[Rider App]
  → ride request
  → [Matching Service]
        → queries Redis Geo for nearby drivers
        → sends offer to selected driver
        → [Driver App] accepts

[Trip Service]
  → manages active trip state
  → streams location to rider via WebSocket

[Pricing Service]
  → calculates surge multiplier from supply/demand ratio
  → feeds pricing to Matching Service

Geospatial indexing: geohashing vs quadtree

The architecture above uses Redis GEO (geohash-based) — worth naming the alternative explicitly. A quadtree recursively subdivides 2D space into four quadrants, going deeper only where point density is high, which adapts naturally to uneven driver distribution (dense in a city center, sparse in a suburb) without manual tuning. Geohashing (fixed-precision string encoding of lat/lng into a sorted key) is simpler to implement on top of an existing key-value store (exactly why Redis GEO works the way it does) and enables straightforward proximity queries via key-prefix matching, but its FIXED grid size doesn't adapt to density the way a quadtree does — a geohash cell sized well for a dense city center is often far too coarse or too fine elsewhere. Redis GEO's real-world convenience (a production-ready primitive requiring no custom index to build/maintain) usually outweighs a quadtree's better density-adaptivity for most ride-sharing scale.

Real-time location updates: WebSocket vs polling

The Trip Service above streams location via WebSocket specifically because ride tracking is latency-sensitive and genuinely bidirectional-feeling (the rider expects near-instant position updates without requesting them). Polling (the rider's app periodically requesting the driver's current position) would work but adds latency (bounded by the poll interval) and wasted requests when nothing has changed — the same WebSocket-vs-polling tradeoff covered generally in Design WhatsApp's real-time delivery discussion applies directly here.

API Design

API Design

// Driver
PUT /drivers/{driverId}/location
Body: { lat, lng, heading, speed }

PATCH /drivers/{driverId}/status  { status: AVAILABLE | ON_TRIP | OFFLINE }

// Rider
POST /rides/request
Body: { riderId, pickup: {lat,lng}, destination: {lat,lng} }
Response: { rideId, driverEta, estimatedFare }

GET /rides/{rideId}/driver-location  → real-time via WebSocket

// Matching
GET /drivers/nearby?lat=X&lng=Y&radius=2km&limit=10

Database Design

Database Design

Driver locations (Redis GEO — O(log N) geospatial queries)

GEOADD drivers:available <lng> <lat> "driver:42"
GEOSEARCH drivers:available FROMMEMBER <point> BYRADIUS 2 km ASC COUNT 10

Trips (PostgreSQL — ACID, payment reconciliation)

rides
  id          UUID    PK
  rider_id    UUID
  driver_id   UUID
  pickup      POINT   (PostGIS geometry)
  destination POINT
  status      ENUM    (REQUESTED, ACCEPTED, ONGOING, COMPLETED, CANCELLED)
  started_at  TIMESTAMP
  ended_at    TIMESTAMP
  fare        DECIMAL

Trip tracking (Cassandra — time-series location history)

trip_location
  trip_id     UUID    PK
  recorded_at TIMEUUID
  lat, lng    DOUBLE

Scaling Strategy

Scaling

Geospatial matching at scale

Redis GEO uses GeoHash under the hood — O(log N) radius search. With 1M active drivers:

  • GEOSEARCH radius 2km returns results in <1ms
  • Partition drivers by city (each city has its own Redis key)

Driver matching algorithm

  1. Query Redis GEO for nearest 10 available drivers
  2. Filter by vehicle type, rating
  3. Offer ride to nearest driver (5-second acceptance window)
  4. If rejected, offer to next driver

Surge pricing

surge_multiplier = demand / supply
where demand = ride_requests_last_10min in zone
      supply = available_drivers_last_10min in zone

if surge > 1.5: show surge warning to rider

Matching algorithm trade-offs: nearest driver vs utilization balancing

The scaling section above describes nearest-available-driver matching — simple, minimizes rider wait time for that specific request. The alternative worth naming: balancing driver utilization across a zone, deliberately NOT always picking the geometrically nearest driver, instead factoring in each nearby driver's recent idle time or earnings — this improves fairness and overall driver retention/satisfaction across the whole platform, at the cost of occasionally giving an individual rider a slightly longer wait than pure nearest-driver would. Production ride-sharing systems generally blend both: nearest-driver as the primary signal, with utilization as a secondary tie-breaker among close candidates, rather than purely optimizing one metric.

Handling driver/rider disconnects and ride-state consistency

Mobile network instability means the Trip Service can't assume a continuous connection — a driver's app losing connectivity mid-trip shouldn't corrupt ride state or leave the rider unable to see any updates. The standard approach: the Trip Service treats itself as the single source of truth for ride state (not the client apps), with each app reconnecting and re-syncing full current state on reconnect rather than relying on a continuous stream of incremental updates it might have partially missed. A brief location staleness during a disconnect is an acceptable, expected condition (shown as 'reconnecting' in the rider UI) rather than a failure requiring special-case handling — the system is explicitly designed to tolerate transient disconnects as normal operation, not an edge case.

Trade-offs

  • Redis GEO vs PostGIS: Redis GEO is faster (in-memory, O(log N)); PostGIS supports complex polygon queries and is durable. Use Redis for real-time matching, PostGIS for analytics.
  • Push vs poll for driver location: Drivers push every 5s regardless. Riders poll every 3s for ongoing trips (or WebSocket for real-time map updates).
  • Matching algorithm: greedy nearest-driver is fast but sub-optimal. ML-based matching (considering traffic, driver idle time) improves ETA accuracy but adds latency.

Bottlenecks

  • Location write storm: 200K writes/sec to Redis. Use pipeline batching and Redis Cluster.
  • Matching hotspots: airport, stadium events create thousands of simultaneous requests. Queue requests; serve in order.
  • ETA accuracy: poor ETA erodes trust. Integrate with Google Maps / Here Maps API for real-time traffic.

Failure Scenarios

  • Redis GEO down: fall back to PostgreSQL PostGIS. Matching degrades from <1ms to ~10ms — still acceptable.
  • Matching Service down: riders see 'no drivers available'. Trip requests queue; retry when service recovers.
  • Driver app crash: trip status maintained server-side. Driver reconnects and resumes trip.

Previous · Case study

Design a Search Autocomplete System

Next · Case study

Design a Web Crawler