{"slug": "system-design-surge-pricing-algorithm-how-ride-hailing-engines-calculate-surge", "title": "[System Design] Surge Pricing Algorithm: How Ride-Hailing Engines Calculate Surge Rate in Real Time", "summary": "A developer details how ride-hailing platforms like Uber and Grab calculate surge pricing in real time using a demand/supply ratio per H3 hexagon cell, recalculated every 30–60 seconds via a lookup table or ML model. The system ingests driver locations and ride requests through Kafka, aggregates them in Flink, and feeds the ratio into a pricing engine that outputs surge multipliers cached in Redis for rider and driver apps.", "body_md": "Series context:This is Part 5 of the[Real-Time Ride-Hailing Architecture]series. For location ingestion and geospatial indexing, start at[Part 1].\n\n**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.\n\n{{< faq q=\"What is surge rate?\" >}}\n\nSurge 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.\n\n{{< /faq >}}\n\n{{< faq q=\"How is surge rate calculated?\" >}}\n\nThe 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.\n\n{{< /faq >}}\n\nOn 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:\n\n**Surge Pricing** (or Dynamic Pricing) is not merely a tool to increase revenue — it is a **marketplace equilibrium mechanism**:\n\n```\nPrice increases → Two simultaneous effects:\n\n1. SUPPLY INCREASES: Drivers see red zones (high prices) on their heatmap\n                     → They move toward those areas to earn more\n                     → The number of available drivers in the area increases\n\n2. DEMAND DECREASES: Riders see high prices → Some choose to wait, take a bus,\n                     or walk → The number of ride requests drops\n\n→ Supply and demand gradually return to EQUILIBRIUM\n→ Wait times are reduced for riders who truly need a car\n┌────────────────────────────────────────────────────────────────┐\n│                      DATA PIPELINE                              │\n│                                                                  │\n│  Kafka Topic              Flink Stream Processing                │\n│  \"driver.location\"  ───►  ┌────────────────────┐                │\n│  \"ride.requests\"    ───►  │  Supply-Demand      │                │\n│                           │  Aggregator         │                │\n│                           │  (per H3 cell,      │                │\n│                           │   5-min window)     │                │\n│                           └─────────┬──────────┘                │\n│                                     │                            │\n│                                     ▼                            │\n│                           ┌────────────────────┐                │\n│                           │  Pricing Engine     │                │\n│                           │  (Surge Calculator) │                │\n│                           └─────────┬──────────┘                │\n│                                     │                            │\n│                           ┌─────────▼──────────┐                │\n│                           │  Redis Cache        │                │\n│                           │  (Surge Multipliers) │                │\n│                           └─────────┬──────────┘                │\n│                                     │                            │\n│                    ┌────────────────┼────────────────┐           │\n│                    ▼                ▼                ▼           │\n│              Rider App        Driver App       Matching Engine   │\n│              (Shows price)    (Heatmap)        (Weighs cost)    │\n└────────────────────────────────────────────────────────────────┘\n```\n\nSurge 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.\n\n```\nHo Chi Minh City is divided into ~200 H3 cells (Resolution 7)\n\nCell A (District 1 - Center): Supply=5,  Demand=30  → Surge 3.2x\nCell B (District 7 - Suburb): Supply=20, Demand=15  → Surge 1.0x (normal)\nCell C (Airport):             Supply=8,  Demand=40  → Surge 4.0x\nCell D (District 9 - Outskirts): Supply=12, Demand=3   → Surge 1.0x\n```\n\nJust like in e-commerce [allocation algorithms](https://dev.to/series/ecommerce-order-allocation/part-3-allocation-algorithms/) that decide which warehouse fulfills an order, the surge engine evaluates resources dynamically.\n\n```\nsurge_multiplier = f(demand / supply)\n\nWhere:\n  supply  = Number of AVAILABLE drivers in the H3 cell (last 5 mins)\n  demand  = Number of ride requests in the H3 cell (last 5 mins)\n\nExample simple formula (illustrative):\n  ratio = demand / supply\n\n  if ratio <= 1.0:  surge = 1.0 (normal price)\n  if ratio == 2.0:  surge = 1.5\n  if ratio == 3.0:  surge = 2.0\n  if ratio >= 5.0:  surge = 3.5 (maximum cap)\n```\n\nIn reality, Uber doesn't use a simple linear formula. They use **ML models** to calculate optimal prices based on a multitude of factors:\n\n| Input Feature | Meaning |\n|---|---|\n| Supply count | Number of idle drivers in the cell |\n| Demand count | Number of requests in a sliding window |\n| Historical patterns | Supply-demand patterns by hour/day of the week |\n| Weather data | Raining → demand rises, supply drops |\n| Events | Large events (concerts, football games)? |\n| Conversion rate | What % of riders still book at the current surge price? |\n| Neighboring cells | Surge levels in adjacent cells (spillover effect) |\n\n```\nContinuous feedback loop:\n\n1. Surge = 3.0x → Many riders cancel (conversion rate drops from 70% → 30%)\n2. Engine realizes: price is too high, riders are abandoning\n3. Lowers surge to 2.0x → Conversion rate recovers to 60%\n4. Simultaneously, drivers arrive (supply increases) → ratio drops\n5. Surge continues dropping to 1.5x → 1.0x\n\nThis entire process happens automatically over a few minutes.\n```\n\nSurge 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.\n\n```\nHeatmap Visualization:\n\n  ┌────────────────────────────────────┐\n  │                                    │\n  │      🟢          🟡               │\n  │            🟢         🟡          │\n  │      🟢   District 7     🔴       │\n  │            🟢    🟡  🔴 District 1│\n  │      🟢        🟡  🔴 🔴         │\n  │                   🔴              │\n  │               🟡                  │\n  │                                    │\n  └────────────────────────────────────┘\n\n  🟢 = 1.0x (normal, surplus of drivers)\n  🟡 = 1.5-2.0x (moderate demand)\n  🔴 = 2.5x+ (very high demand, great earning potential)\n```\n\nThe heatmap is pushed to the driver app via **WebSockets** (or gRPC streams):\n\n```\nServer → WebSocket Push → Driver App\n\nPayload every 30 seconds:\n{\n  \"heatmap\": [\n    {\"h3\": \"872a100d6ffffff\", \"surge\": 3.2, \"color\": \"#FF0000\"},\n    {\"h3\": \"872a100d7ffffff\", \"surge\": 1.0, \"color\": \"#00FF00\"},\n    {\"h3\": \"872a100d8ffffff\", \"surge\": 1.8, \"color\": \"#FFAA00\"}\n  ],\n  \"updated_at\": \"2026-05-06T20:30:00Z\"\n}\n```\n\nUber and Grab don't just react to current surges — they **predict surges** before they happen:\n\n```\nPredictive Model:\n\nInputs:\n  - Current time: 17:00 (rush hour approaching)\n  - Day: Friday (weekend → demand rises)\n  - Weather: Rain forecasted at 17:30\n  - Events: Concert at the Stadium at 20:00\n  - History: The last 4 Fridays also surged to 2.5x at 17:30\n\nOutput:\n  - Prediction: Surge will hit 2.8x in the Stadium area at 17:30\n  - Action: Send notifications to nearby drivers 15 minutes BEFORE\n    \"High demand expected near the Stadium soon, drive there to earn more!\"\nPrice shown to rider: \"Surge 2.5x\"\nFinal Price = Base Fare × 2.5\nProblem: Riders didn't know the total cost before getting in → Surprises, complaints\nShown to rider: \"Price: 125,000 VND\" (fixed before booking)\n\nPrice is calculated from:\n  base_fare + (distance × per_km_rate) + (time × per_min_rate)\n  + surge_premium\n  + route_specific_adjustments (e.g., predicted traffic jams)\n\nThe rider knows the exact price upfront → Much more transparent\n-- Redis: Stores the surge multiplier for each H3 cell\n-- Key pattern: surge:{resolution}:{h3_cell_id}\n-- TTL: 60 seconds (auto-expires if not updated → falls back to 1.0x)\n\nSET surge:7:872a100d6ffffff \"3.2\" EX 60\nSET surge:7:872a100d7ffffff \"1.0\" EX 60\nSET surge:7:872a100d8ffffff \"1.8\" EX 60\n\n-- When Rider App requests a price:\nGET surge:7:872a100d6ffffff → \"3.2\"\n-- The API Gateway uses this value to calculate the Upfront Price\n```\n\n| Risk | Solution |\n|---|---|\n| Drivers deliberately turning off apps to create artificial scarcity | Detect patterns: many drivers going offline simultaneously → flag |\n| Drivers only accepting high surge rides, rejecting normal rides | Low acceptance rate → lower priority in matching algorithm |\n| Extremely high surges causing massive backlash | Maximum cap (e.g., 5.0x), soft caps based on conversion rates |\n| \"Flickering\" surge (rapidly fluctuating prices) | Smoothing: surge can only increase/decrease by a max of 0.5x every 30 seconds |\n\n**What is surge rate in ride-hailing?**\n\nSurge 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.\n\n**Why does surge rate exist?**\n\nSurge 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.\n\n**What is a normal surge rate vs. a high surge rate?**\n\nA 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.\n\n**How long does a surge rate last?**\n\nSurge 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.\n\n**How does the surge pricing engine work technically?**\n\nThe 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.\n\nIn 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].\n\n*This post was originally published on my blog at Surge Pricing Algorithm: How Ride-Hailing Engines Calculate Surge Rate in Real Time.*\n\n**Hi, I'm Lê Tuấn Anh (vesviet) 👋**\n\n*I am a Senior Go Backend Architect & Distributed Systems Engineer with 17+ years of experience building high-traffic platforms (25M+ requests/month).*\n\n*If you enjoyed this deep-dive, let's connect on LinkedIn or explore my consulting services at tanhdev.com/hire.*", "url": "https://wpnews.pro/news/system-design-surge-pricing-algorithm-how-ride-hailing-engines-calculate-surge", "canonical_source": "https://dev.to/vesviet/system-design-surge-pricing-algorithm-how-ride-hailing-engines-calculate-surge-rate-in-real-time-li8", "published_at": "2026-06-16 12:02:51+00:00", "updated_at": "2026-06-16 12:17:18.002119+00:00", "lang": "en", "topics": ["machine-learning", "large-language-models", "ai-products", "ai-infrastructure", "developer-tools"], "entities": ["Uber", "Grab", "Kafka", "Flink", "Redis", "H3"], "alternates": {"html": "https://wpnews.pro/news/system-design-surge-pricing-algorithm-how-ride-hailing-engines-calculate-surge", "markdown": "https://wpnews.pro/news/system-design-surge-pricing-algorithm-how-ride-hailing-engines-calculate-surge.md", "text": "https://wpnews.pro/news/system-design-surge-pricing-algorithm-how-ride-hailing-engines-calculate-surge.txt", "jsonld": "https://wpnews.pro/news/system-design-surge-pricing-algorithm-how-ride-hailing-engines-calculate-surge.jsonld"}}