πŸŽ‰ Launch Sale: Get 30% off annual plans with code LAUNCH30

← Back to Blog
Location Servicesβ€’Advancedβ€’36 min read

Design a Ride-Hailing System

Asked at:UberLyftGrabOlaDiDi
Tech:ReplicationAvailabilityRedisWebSocketSSEIdempotency

Two Seconds to Find a Driver

A rider opens the app, taps "Request Ride," and expects a driver to appear on their screen almost instantly. Behind that expectation is a system that must ingest 500,000 GPS updates per second from drivers around the world, find the best available driver within a 2-second window, send them an offer over an unreliable mobile network, handle the case where that driver does not respond, try the next candidate, and β€” once a driver accepts β€” maintain a synchronized real-time view of the trip for both rider and driver, all while ensuring that no two riders are assigned the same driver and no trip enters an impossible state.

Ride-hailing is fundamentally different from the systems we have designed so far. A URL shortener serves a static mapping. A chat system delivers messages to known recipients. A notification system pushes content through channels. Ride-hailing makes real-time decisions under uncertainty: the driver's location is already stale by the time you query it, the best candidate might reject the offer, and the rider might cancel while you are still searching. Every component must be designed for speed, correctness under concurrency, and graceful degradation when data is imperfect.

This post walks through designing an Uber-style ride-hailing system from first principles. We will build progressively: a correct trip state machine first, then fast geospatial matching, then real-time delivery, and finally reliability hardening. Every decision will be justified by capacity math and grounded in how geospatial systems and mobile networks actually behave.

Let us begin.

1. Requirements β€” What the System Must Do in Two Seconds

Before drawing any boxes, we need to agree on the four actions the system must support and the performance constraints that shape every choice.

Functional Requirements

  1. Rider requests a ride. A rider specifies pickup and drop-off locations and submits a request. The system provides an estimated fare and begins searching for a driver.
  2. Nearby drivers are matched. The system identifies available drivers near the pickup point, ranks them, and assigns the best one. This must happen within 2 seconds in dense cities.
  3. Real-time trip updates. Both rider and driver see each other's location on a live map, with trip state changes (driver arriving, ride started, approaching destination) reflected immediately.
  4. Trip lifecycle tracking. Every trip follows a strict state machine: REQUESTED β†’ MATCHED β†’ DRIVER_EN_ROUTE β†’ ARRIVED β†’ ON_TRIP β†’ COMPLETED (or CANCELLED from certain states). State transitions must be atomic β€” no duplicate assignments, no impossible state jumps.

Non-Functional Requirements

  1. Match decision p95 under 2 seconds in active cities. This is the total budget from ride request to driver assignment β€” including geospatial search, candidate ranking, offer delivery, and driver response.
  2. High availability for dispatch and trip state. A rider who tapped "Request" must get a match attempt; a trip in progress must not lose its state.
  3. Location ingestion at 500,000 writes per second. Every online driver sends a GPS update every 3 seconds. This is the highest-throughput path in the system and must not bottleneck matching.
  4. Idempotent request and accept flows. Mobile networks are lossy β€” riders double-tap "Request," drivers double-tap "Accept." The system must produce exactly one trip per intent.
  5. Graceful handling of stale data and disconnects. Drivers lose signal, go through tunnels, or background the app. The system must detect and quarantine stale data rather than dispatching to phantom drivers.

Scope Control

In scope: matching, location ingestion, trip state machine, dispatch offers, basic ETA, fare estimation.

Out of scope: detailed fraud scoring, ML surge pricing model internals, payment ledger, driver onboarding.

Now that we know what we are building, we need to understand the scale. The numbers will determine whether we can search all drivers or must use spatial indexing, whether we can store locations in a database or need an in-memory store, and how many WebSocket connections we must support.

Login to continue reading

You reached the preview limit. Sign in to unlock the remaining sections.

Continue Learning

πŸŽ‰ Launch Sale!

30% off annual plans with code LAUNCH30

View Pricing