Series context:This is Part 5 of the[Real-Time Ride-Hailing Architecture]series. For location ingestion and geospatial indexing, start at[Part 1].
Surge rate is the real-time price multiplier (e.g., 2.0Γ) applied by ride-hailing platforms when ride demand in a geographic zone exceeds available driver supply. It is recalculated every 30β60 seconds per H3 hexagon cell using a demand/supply ratio fed into a lookup table or ML model.
{{< faq q="What is surge rate?" >}}
Surge rate (also called surge pricing or surge multiplier) is the real-time price multiplier that ride-hailing platforms like Uber and Grab apply when demand for rides exceeds the available supply of drivers in a geographic zone. A surge rate of 2.0x means the rider pays twice the base fare.
{{< /faq >}}
{{< faq q="How is surge rate calculated?" >}}
The surge rate is calculated by a pricing engine that evaluates the ratio of incoming ride requests (demand) versus available drivers (supply) in a specific H3 hexagon cell over a rolling time window (typically 5 minutes). The ratio is fed into a lookup table or ML model that outputs the surge multiplier.
{{< /faq >}}
On New Year's Eve, during heavy rain, or at rush hour β the demand for rides skyrockets, but the number of available drivers remains unchanged. If prices were kept fixed:
Surge Pricing (or Dynamic Pricing) is not merely a tool to increase revenue β it is a marketplace equilibrium mechanism:
Price increases β Two simultaneous effects:
1. SUPPLY INCREASES: Drivers see red zones (high prices) on their heatmap
β They move toward those areas to earn more
β The number of available drivers in the area increases
2. DEMAND DECREASES: Riders see high prices β Some choose to wait, take a bus,
or walk β The number of ride requests drops
β Supply and demand gradually return to EQUILIBRIUM
β Wait times are reduced for riders who truly need a car
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DATA PIPELINE β
β β
β Kafka Topic Flink Stream Processing β
β "driver.location" ββββΊ ββββββββββββββββββββββ β
β "ride.requests" ββββΊ β Supply-Demand β β
β β Aggregator β β
β β (per H3 cell, β β
β β 5-min window) β β
β βββββββββββ¬βββββββββββ β
β β β
β βΌ β
β ββββββββββββββββββββββ β
β β Pricing Engine β β
β β (Surge Calculator) β β
β βββββββββββ¬βββββββββββ β
β β β
β βββββββββββΌβββββββββββ β
β β Redis Cache β β
β β (Surge Multipliers) β β
β βββββββββββ¬βββββββββββ β
β β β
β ββββββββββββββββββΌβββββββββββββββββ β
β βΌ βΌ βΌ β
β Rider App Driver App Matching Engine β
β (Shows price) (Heatmap) (Weighs cost) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Surge pricing is not calculated for an entire city β it is calculated for individual H3 hexagons. Uber uses Resolution 7 (each cell ~5 kmΒ²), which is large enough to be statistically significant but small enough to reflect hyper-local conditions.
Ho Chi Minh City is divided into ~200 H3 cells (Resolution 7)
Cell A (District 1 - Center): Supply=5, Demand=30 β Surge 3.2x
Cell B (District 7 - Suburb): Supply=20, Demand=15 β Surge 1.0x (normal)
Cell C (Airport): Supply=8, Demand=40 β Surge 4.0x
Cell D (District 9 - Outskirts): Supply=12, Demand=3 β Surge 1.0x
Just like in e-commerce allocation algorithms that decide which warehouse fulfills an order, the surge engine evaluates resources dynamically.
surge_multiplier = f(demand / supply)
Where:
supply = Number of AVAILABLE drivers in the H3 cell (last 5 mins)
demand = Number of ride requests in the H3 cell (last 5 mins)
Example simple formula (illustrative):
ratio = demand / supply
if ratio <= 1.0: surge = 1.0 (normal price)
if ratio == 2.0: surge = 1.5
if ratio == 3.0: surge = 2.0
if ratio >= 5.0: surge = 3.5 (maximum cap)
In reality, Uber doesn't use a simple linear formula. They use ML models to calculate optimal prices based on a multitude of factors:
| Input Feature | Meaning |
|---|---|
| Supply count | Number of idle drivers in the cell |
| Demand count | Number of requests in a sliding window |
| Historical patterns | Supply-demand patterns by hour/day of the week |
| Weather data | Raining β demand rises, supply drops |
| Events | Large events (concerts, football games)? |
| Conversion rate | What % of riders still book at the current surge price? |
| Neighboring cells | Surge levels in adjacent cells (spillover effect) |
Continuous feedback loop:
1. Surge = 3.0x β Many riders cancel (conversion rate drops from 70% β 30%)
2. Engine realizes: price is too high, riders are abandoning
3. Lowers surge to 2.0x β Conversion rate recovers to 60%
4. Simultaneously, drivers arrive (supply increases) β ratio drops
5. Surge continues dropping to 1.5x β 1.0x
This entire process happens automatically over a few minutes.
Surge pricing doesn't just affect the cost for the rider β it generates a Heatmap displayed on the driver's app, guiding them to areas with high demand.
Heatmap Visualization:
ββββββββββββββββββββββββββββββββββββββ
β β
β π’ π‘ β
β π’ π‘ β
β π’ District 7 π΄ β
β π’ π‘ π΄ District 1β
β π’ π‘ π΄ π΄ β
β π΄ β
β π‘ β
β β
ββββββββββββββββββββββββββββββββββββββ
π’ = 1.0x (normal, surplus of drivers)
π‘ = 1.5-2.0x (moderate demand)
π΄ = 2.5x+ (very high demand, great earning potential)
The heatmap is pushed to the driver app via WebSockets (or gRPC streams):
Server β WebSocket Push β Driver App
Payload every 30 seconds:
{
"heatmap": [
{"h3": "872a100d6ffffff", "surge": 3.2, "color": "#FF0000"},
{"h3": "872a100d7ffffff", "surge": 1.0, "color": "#00FF00"},
{"h3": "872a100d8ffffff", "surge": 1.8, "color": "#FFAA00"}
],
"updated_at": "2026-05-06T20:30:00Z"
}
Uber and Grab don't just react to current surges β they predict surges before they happen:
Predictive Model:
Inputs:
- Current time: 17:00 (rush hour approaching)
- Day: Friday (weekend β demand rises)
- Weather: Rain forecasted at 17:30
- Events: Concert at the Stadium at 20:00
- History: The last 4 Fridays also surged to 2.5x at 17:30
Output:
- Prediction: Surge will hit 2.8x in the Stadium area at 17:30
- Action: Send notifications to nearby drivers 15 minutes BEFORE
"High demand expected near the Stadium soon, drive there to earn more!"
Price shown to rider: "Surge 2.5x"
Final Price = Base Fare Γ 2.5
Problem: Riders didn't know the total cost before getting in β Surprises, complaints
Shown to rider: "Price: 125,000 VND" (fixed before booking)
Price is calculated from:
base_fare + (distance Γ per_km_rate) + (time Γ per_min_rate)
+ surge_premium
+ route_specific_adjustments (e.g., predicted traffic jams)
The rider knows the exact price upfront β Much more transparent
-- Redis: Stores the surge multiplier for each H3 cell
-- Key pattern: surge:{resolution}:{h3_cell_id}
-- TTL: 60 seconds (auto-expires if not updated β falls back to 1.0x)
SET surge:7:872a100d6ffffff "3.2" EX 60
SET surge:7:872a100d7ffffff "1.0" EX 60
SET surge:7:872a100d8ffffff "1.8" EX 60
-- When Rider App requests a price:
GET surge:7:872a100d6ffffff β "3.2"
-- The API Gateway uses this value to calculate the Upfront Price
| Risk | Solution |
|---|---|
| Drivers deliberately turning off apps to create artificial scarcity | Detect patterns: many drivers going offline simultaneously β flag |
| Drivers only accepting high surge rides, rejecting normal rides | Low acceptance rate β lower priority in matching algorithm |
| Extremely high surges causing massive backlash | Maximum cap (e.g., 5.0x), soft caps based on conversion rates |
| "Flickering" surge (rapidly fluctuating prices) | Smoothing: surge can only increase/decrease by a max of 0.5x every 30 seconds |
What is surge rate in ride-hailing?
Surge rate is the multiplier applied to a ride's base price during peak demand periods. A surge rate of 1.5x on a $10 base fare means the rider pays $15. The surge rate is calculated per geographic zone (H3 cell) and updated every 30β60 seconds.
Why does surge rate exist?
Surge rate is a market-clearing mechanism, not just a revenue tool. When demand outpaces supply, a higher surge rate simultaneously attracts more drivers to the area (supply increase) and filters out lower-urgency ride requests (demand decrease), restoring equilibrium and reducing wait times for riders who genuinely need a car.
What is a normal surge rate vs. a high surge rate?
A surge rate of 1.0x is the baseline (no surge). Rates between 1.2xβ1.8x are considered moderate surge. Rates above 2.0x indicate heavy demand imbalance. Most platforms enforce a hard cap (e.g., 5.0x) to prevent extreme price spikes that damage user trust.
How long does a surge rate last?
Surge rates are recalculated every 30β60 seconds using a sliding window over the last 5 minutes of supply-demand data. In most cases, a surge event lasts 15β45 minutes before drivers repositioning to the zone restore equilibrium.
How does the surge pricing engine work technically?
The engine ingests driver location events and ride request events from a message broker (Kafka). A stream processor (Apache Flink) aggregates supply and demand counts per H3 cell on a 5-minute tumbling window. The output is a demand/supply ratio that maps to a surge multiplier via a lookup table or an ML model. The resulting multiplier is cached in Redis with a 60-second TTL and read by the API gateway at price-calculation time.
In the final part, we will explore RAMEN β Uber's real-time communication infrastructure, which solves the problem of pushing instant notifications to millions of devices simultaneously. Continue reading[Part 6 β RAMEN & Real-time Communication].
This post was originally published on my blog at Surge Pricing Algorithm: How Ride-Hailing Engines Calculate Surge Rate in Real Time.
Hi, I'm LΓͺ TuαΊ₯n Anh (vesviet) π
I am a Senior Go Backend Architect & Distributed Systems Engineer with 17+ years of experience building high-traffic platforms (25M+ requests/month).
If you enjoyed this deep-dive, let's connect on LinkedIn or explore my consulting services at tanhdev.com/hire.