High-Level Design Tutorial 0/42 lessons ~6 min read Lesson 39

    Ride Booking System

    Design ride booking like Uber — riders request trips, drivers accept, real-time tracking, fare calculation, and payment settlement.

    Course progress0%
    Focus
    10 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Design ride booking like Uber — riders request trips, drivers accept, real-time tracking, fare calculation, and payment settlement. Combines geo matching, surge pricing, trip state machine, and dual-sided mobile apps.

    Location updates every few seconds from millions of drivers stress ingestion pipeline. Matching latency target under 30 seconds in dense cities.

    Understanding the topic

    Key concepts

    • Trip states: REQUESTED → MATCHED → IN_PROGRESS → COMPLETED / CANCELLED.
    • Supply-demand: drivers online in geo cell; riders request pickup/dropoff.
    • Matching: broadcast offer to nearest N drivers; first accept wins.
    • Surge: multiplier from demand/supply ratio per geo hex.
    • Fare: base + distance + time + surge; calculated at end with GPS trail.
    • Payment: authorize estimate, capture final, driver payout async.
    text
    flowchart TB
    Rider --> MatchSvc
    MatchSvc --> Geo
    Driver --> LocationStream
    MatchSvc --> TripSvc

    Internal architecture

    Architecture overview

    text
    flowchart TB
    Rider --> MatchSvc
    MatchSvc --> Geo
    Driver --> LocationStream
    MatchSvc --> TripSvc

    Step-by-step explanation

    1. Rider POST /trips → Trip Service creates REQUESTED, publishes to Matching.
    2. Matching queries Redis GEO drivers within radius expanding until accept.
    3. Driver POST /trips/{id}/accept with distributed lock on tripId.
    4. Location stream: driver app → Kafka → stream processor updates Redis + rider map WS.
    5. Trip complete → Pricing engine → Payment capture → Driver wallet credit via payout queue.
    6. Surge service consumes demand/supply counters per H3 hex cell.

    Informative example

    Trip request and driver accept with optimistic locking:

    java
    @Service
    public class TripService {
    private final TripRepository trips;
    private final MatchingClient matching;
    private final StringRedisTemplate redis;
    public TripResponse requestTrip(TripRequest req, String riderId) {
    Trip trip = trips.save(Trip.requested(riderId, req.pickup(), req.dropoff()));
    matching.findDriver(trip.id(), req.pickup());
    return TripResponse.from(trip);
    }
    public TripResponse accept(String tripId, String driverId) {
    String lockKey = "trip:lock:" + tripId;
    Boolean ok = redis.opsForValue().setIfAbsent(lockKey, driverId, Duration.ofSeconds(15));
    if (!Boolean.TRUE.equals(ok)) throw new TripAlreadyMatchedException();
    Trip trip = trips.findById(tripId).orElseThrow();
    trip.match(driverId);
    trips.save(trip);
    return TripResponse.from(trip);
    }
    }

    H3 hex indexing for surge. Separate read-heavy map tile service. Outbox events for billing.

    Real-world use

    Real-world use cases

    • Ride-hailing Uber/Lyft model.
    • Fleet logistics B2B dispatch.
    • Ambulance emergency prioritization queue.
    • Autonomous vehicle fleet coordinator future variant.

    Best practices

    • Cell-based architecture per city for fault isolation.
    • Idempotent trip request from rider double-tap.
    • GPS trail stored compressed for fare dispute.
    • Driver background check separate service boundary.
    • Cancel policy fees in state machine transitions.
    • Load test location ingestion separately from matching.

    Common mistakes

    • Global matching DB scan — O(n) drivers unacceptable.
    • No lock on accept — two drivers same trip.
    • Synchronous long polling blocks matching thread.
    • Surge applied without cap — PR disaster.
    • Payment capture before trip complete without adjustment logic.

    Advanced interview questions

    Q1BeginnerCore trip states?
    Requested, matched, in progress, completed, cancelled — drive notifications and billing.
    Q2BeginnerHow match rider to driver?
    Geo index nearest available drivers, broadcast offer, first accept with distributed lock on trip.
    Q3IntermediateLocation update pipeline?
    Driver GPS → Kafka high throughput → stream update Redis GEO → WebSocket to rider app.
    Q4IntermediateSurge pricing design?
    Track demand requests and supply online per geo hex; dynamic multiplier published to fare quote API.
    Q5AdvancedDesign Uber global 100M monthly trips.
    City cells, Kafka location 1M msgs/sec sharded, Redis GEO per city, Cassandra trips, payment saga, surge Flink job, multi-region active, DR runbooks, map CDN tiles.

    Summary

    Ride HLD combines geo matching, trip FSM, and location streaming. Redis GEO and cell architecture enable sub-second proximity queries. Distributed lock prevents double driver assignment. Surge pricing from real-time demand/supply analytics. Payment authorize/capture aligns with trip completion. Online payments deep-dive fraud and ledger patterns next.

    Ready to mark this lesson complete?Track your journey across the entire course.