#15 Stream Processing/Real-time
Uber Surge Pricing
Raise and lower ride prices per neighbourhood, minute by minute, from live supply and demand.
What is being asked
Design surge pricing: compute a price multiplier for each small area of a city from how many riders are requesting and how many drivers are free, and apply it consistently to fare quotes.
Requirements
Functional
- Ingest driver locations and availability, and ride requests.
- Compute a multiplier per area every minute or less.
- Quote a price that the rider is then guaranteed for a short time.
Non-functional
- Low latency from a change in demand to a change in price.
- Stable: prices must not flicker between values.
- Always answer a quote, falling back to no surge if the pipeline is down.
Design
- The city is divided into hexagonal cells. Every event is assigned to a cell.
- A stream processor keeps, per cell, a sliding count of open requests and available drivers over the last few minutes.
- A pricing model turns the ratio into a multiplier, smoothing over time and over neighbouring cells.
- Multipliers are written to a fast store. The quote service reads the cell's multiplier, computes the fare and returns a quote with a token that locks that price for a couple of minutes.
Key decisions and trade-offs
- Cell size. Small cells react precisely but have noisy counts; large cells are stable but blunt. Smoothing with neighbours helps.
- Sliding windows and smoothing prevent a price that jumps every few seconds, which riders and drivers both distrust.
- Price lock. The quoted price must hold when the rider confirms, so the quote carries a signed token rather than being recomputed.
- Graceful fallback. If the pipeline lags, serve the last known multiplier with a time limit, then no surge.
Follow-up questions
- How do you stop drivers colluding to go offline and trigger surge?
- How would you predict demand for a concert ending in 20 minutes?
- What happens at the border between a surging cell and a normal one?
- How do you test a new pricing model safely?