0) Problem Restatement
OpenAI asked: you operate a ride-hailing platform. Design a system that sets surge multipliers (e.g., 1.5x) for each region in near real time. The pricing strategy must balance rider experience (not too expensive, rides available), driver supply (higher prices attract drivers to busy areas), and marketplace efficiency (most requests get matched quickly).
1) Why Surge Exists (simply)
When many people request rides in one area and few drivers are there, wait times explode. A higher price (1) reduces some demand (people wait or walk) and (2) attracts drivers to that area. The goal is to keep waiting times reasonable, not to maximize price.
2) Architecture
Architecture Diagram
flowchart LR
RQ["Ride requests / app opens"] --> K[("Kafka - demand events")]
DL["Driver locations + status"] --> K2[("Kafka - supply events")]
K --> AGG["Stream aggregation per H3 cell, per minute"]
K2 --> AGG
AGG --> CALC["Surge calculator - every 1-2 min"]
FC["Short-term demand forecast"] --> CALC
CALC --> SM[("Surge map - cell to multiplier, version")]
SM --> QUOTE["Pricing / quote service"]
QUOTE --> APP["Rider app - price shown, locked for N min"]
SM --> DRV["Driver app - heat map"]3) The Calculation
- Zones: split the city into hexagonal cells (e.g., Uber's H3 at a neighborhood size), and group small cells to avoid noisy tiny areas.
- Measure per cell, per minute:
- Demand: ride requests plus app opens (people checking prices), including recently unfulfilled requests.
- Supply: available drivers in or near the cell (plus drivers about to finish trips nearby), and estimated pickup times.
ratio = demand / effective_supply, or better, the predicted ETA / probability a request goes unfulfilled.
- Multiplier: map the imbalance to a multiplier through a curve, e.g., 1.0 when balanced, rising gradually, and capped (e.g., max 3x, lower during emergencies by policy or law).
- Smoothing: combine with the previous value (e.g., exponential smoothing), and limit how fast it can change, so prices don't jump up and down every minute (oscillation). Spatially smooth with neighboring cells to avoid sharp price borders.
- Forecasting: add expected demand spikes (a concert ending, rain starting) to act slightly early.
4) Serving and Fairness
- The surge map (cell → multiplier, version, timestamp) is stored in a fast, replicated store, and read by the quote service in milliseconds.
- When a rider requests a quote, the price is computed with the current multiplier and locked for a few minutes (the rider sees exactly what they'll pay).
- Drivers see a heat map to reposition.
- Guardrails: caps, emergency freezes, and no personalization of surge per rider (fairness), plus logging for audits.
5) Measuring Success (experiments)
- Metrics: request completion rate, pickup ETA, rider conversion (people who accept the price), driver earnings, and cancellations.
- A/B test curve shapes and smoothing parameters, by city or with switchback experiments (alternating time windows), since the marketplace effects spill across users.
6) Wrap-Up
Split cities into H3 cells, stream demand (requests, app opens) and supply (available and soon-available drivers) into per-cell, per-minute aggregates, and every minute or two compute a multiplier from the imbalance (or predicted ETA) through a capped curve, smoothed over time and space and nudged by short-term forecasts. Publish a versioned surge map read by the quote service, lock quoted prices for a few minutes, show drivers the heat map, enforce caps and fairness rules, and tune it all through marketplace experiments.