← marketplace-ops-toolkit
marketplace-ops-toolkit · tool #3

Marketplace Surge Simulator (PID Control) V2

Surge pricing without overshoot. V2 adds polygon-level optimization — a 3×3 city map showing per-zone surge state. Because a city-average surge of 1.0x can hide Downtown at 2.5x (alert) and Suburbs at 0.8x (oversupply) at the same hour. Optimization happens at the polygon, not the aggregate.

Pick a scenario

PID tuning

Reacts to current error. Higher = more aggressive surge response now.
Accumulates error over time. Too high = oscillation in delayed systems.
Reacts to rate of change. Higher = catches spikes. Too high = noisy.

PID performance (city aggregate)

Avg MAPE
0%
Peak MAPE
0%
Peak surge
1.00x
Hours in alert (>20% MAPE)
0h
Demand vs Supply (24h)
How requests and available capacity move over the day.
Demand Supply
Surge Multiplier (PID Output)
What the PID controller asks the pricing system to do, clamped 1.0x–2.5x.
PID surge Naive threshold (1.5x if MAPE>30%)
MAPE — Error Signal
|demand − supply| / demand × 100. Lower is better. Red zone > 20%.
PID-controlled Naive 20% threshold
PID Term Contribution
Which term (P, I, or D) is driving the surge response at each moment.
P · proportional I · integral D · derivative

PID vs Naive — same scenario, head to head

Naive (threshold 1.5x if MAPE > 30%)

0%
avg MAPE · peak 0% · 0h in alert

PID (your current tuning)

0%
avg MAPE · peak 0% · 0h in alert
Pick a scenario to compare.
Why polygon-level matters Real marketplaces aren't one supply-demand curve per city. They're many curves, one per geographic zone. Downtown spikes at rush hour, the airport spikes at flight time, the stadium spikes during events, suburbs barely move. A city-average surge of 1.0x can mean Downtown is at 2.5x (alert) and Suburbs is at 0.8x (oversupply) in the same minute. The aggregate hides the truth. Production marketplace platforms run surge at the polygon (or hex cell) level for exactly this reason. This V2 view runs nine independent PID controllers — one per zone — and visualizes how the same time of day looks wildly different across geography.
Time of day
00:00

City zones — current state

Each polygon is a zone running its own PID surge controller. Color shows current MAPE status. Click any zone to see its detail. Drag the time scrubber above to see how the city evolves across 24h.
MAPE < 15% — balanced 15-30% — watch > 30% — alert
Click a zone
Demand
Supply
MAPE
Surge

Polygon-level vs City-level — head to head (24h)

Same demand and supply data. Two approaches: a single city-wide PID controller vs nine polygon-level PID controllers. Polygon-level optimizes each zone independently and produces lower aggregate MAPE because it doesn't average away local imbalance.
City-level PID · avg MAPE
0%
Polygon-level PID · avg MAPE
0%
Improvement (relative)
0%
Worst polygon at this moment
Drag the scrubber to see how the city evolves and how polygon-level PID outperforms.

How PID surge pricing works

Marketplace platforms balance supply and demand using surge multipliers — pricing that adjusts in real time to bring more drivers/couriers/sellers online when demand exceeds capacity. The classic way to do this is a threshold rule: if imbalance > X%, set surge to 1.5x. It works, but it overshoots and oscillates because there's no feedback memory.

The smarter approach borrows from control theory invented in 1922 by Nicholas Minorsky: the PID controller. PID stands for Proportional, Integral, Derivative — three terms that together compute the right amount of correction to apply at any moment, given how much error there is now, how much has accumulated, and how fast it's changing.

Real-world impact

Illustrative scenarios drawn from operator practice. Numbers are realistic order-of-magnitude estimates, not measurements from any specific deployment.

Case 1: City-average surge masking 4 starving polygons
SetupPricing manager at a ride-hailing operation in a Tier-2 LATAM city running a single citywide surge multiplier on weekday evening peaks.
ProblemCitywide multiplier averaged 1.4x and looked healthy, but 4 outer polygons were stuck at 18 to 22 minute ETAs while downtown sat at 4 minutes, causing roughly 8% trip cancellation in those zones.
Tool surfacedV2 polygon view showed the 3x3 zone grid with two cells in deep undersupply at effective 1.0x while downtown was overshooting at 1.7x, the PID tune was too smooth for spatial variance.
OutcomeZone-level Kp raised on outer cells, cancellation in those polygons dropped from 8% to 3.2%, recovered an estimated $9K per weekday peak in completed trips.
Case 2: Surge oscillation eroding driver trust
SetupMarketplace ops at a delivery platform was running surge updates every 5 minutes and pricing kept swinging 1.0x to 1.8x to 1.1x within a single 30 minute window.
ProblemDriver complaints spiked about "phantom surge" and weekly driver churn climbed roughly 4 points, costing the team about $22K monthly in re-acquisition and onboarding.
Tool surfacedThe simulator showed integral gain was too high and derivative too low, producing classic PID overshoot; smoother coefficients held supply-demand inside the deadband 78% of the time vs 41% in current settings.
OutcomeNew PID coefficients rolled out region by region, driver churn dropped back 3.5 points within 2 cycles, savings around $19K monthly on retention alone.

The formula

error[t] = (demand − supply) / demand × 100 // MAPE as % P_term = Kp × error[t] // react now I_term = Ki × Σ error × dt // remember D_term = Kd × (error[t] − error[t−1]) / dt // anticipate surge[t] = clamp(1.0 + (P + I + D) / 100, 1.0, 2.5)

What each term does

Why AND instead of OR? Each signal alone is too noisy. Volume velocity alone triggers on Black Friday. New-user count alone triggers on marketing campaigns. The intersection — all three crossing simultaneously — is the fingerprint of an attack.

The status tiers

V2 — Polygon-level optimization

V1 ran a single PID controller over the city aggregate. V2 adds a second view: nine independent PID controllers, one per geographic zone. Real production surge systems (Uber's H3 hexes, Lyft's zones, DoorDash's dispatch cells) operate at this level for one reason — city averages hide local imbalance.

A 1.0x city surge can be the average of Downtown at 2.5x and Suburbs at 0.8x. Optimize the average, and Downtown riders wait too long while suburb drivers sit idle. Optimize each zone, and both problems disappear at the cost of slightly more complex control architecture.

How the comparison works

What this simulator is NOT

What this simulator IS

Reference implementation

The Python reference of the (V1) city-level logic is available as surge-pid-reference.py. Polygon-level extension is straightforward: wrap the existing PIDController in a loop over zones, each with its own demand_fn and PID state.

Reading list