Surge Pricing
Taxi & Private Hire › Products › Surge › Surge Pricing
beta
The customer side of Surge: when an area gets genuinely busy, a temporary uplift is added to the fare — both to ease demand and to fund a shared pool that pulls extra drivers toward the hotspot. The uplift follows a configurable curve (where it begins, how steeply it climbs, and a safety ceiling) read against the same busyness signal the capacity system uses. It is locked in at quote time and shown as its own line on the fare, applied after discounts. Surge applies only to eligible everyday trips; important trips such as medical/NEMT and prestige bookings are exempt by default. Operators enable it per company or fleet with an off / shadow / on setting — shadow previews the would-be uplift without ever charging — and it stays in preview until the launch safeguards are in place. The sibling Surge features detect the hotspots, recruit the drivers, and pay out the pool.
A transparent, capped uplift — locked at quote
When a pickup falls inside an active surge zone, a temporary uplift is added to the fare as its own line — so the customer always sees exactly what surge added. It does two jobs: it rations demand by price rather than refusing rides outright, and it funds the driver pool that pulls supply toward the busy area. The amount is locked at the moment of the quote, so it never drifts as the trip is recalculated, and it's capped — surge can never more than double a fare.
Switched on safely — shadow first
Surge is off by default, and you don't have to trust it blind. An operator can run it in shadow: the platform evaluates the surge it would have charged and records it — for as long as you like — without billing anyone. You validate against real demand for weeks before a single customer pays. Only when you switch it on does it bill (and fund the pool), and eligibility is fail-closed — exempt trips are never surged.
The uplift is shaped by the detection curve and funds the driver pool.
Settings
How operators configure this feature.
How surge pricing acts when a busy demand cluster forms: off (no surge), shadow (compute and record what surge would have charged, but never bill the customer — for safe validation), or on (charge it). Starts off; turn on shadow first to see what surge would do before billing anyone. Set per company or per fleet.
Modes: OFF · SHADOW · ON · default OFF · set per client → fleet
Related
- Surge Detection beta
- Driver Subscribing beta
- Pooling the Money beta
- Area Busyness
- Open Dispatch
- Target Zones
Fields
| Field | Type | Description |
|---|---|---|
name | string | |
active | bool | |
priority | integer | |
upliftType | SurgeUpliftType · PERCENTAGE | FIXED_AMOUNT | |
floorBusyness | float | |
vertexBusyness | float | |
vertexUplift | float | |
ceilingBusyness | float | |
maxUplift | float | |
clientId | bigint | Tenant scope. Every tenant-aware entity carries this; `ClientFilter` enforces row-level isolation on read; the multi-tenancy routing layer (`/client/{clientId}`) sets it at create time. Surfaced only under `admin` / `tripLog` groups — never to end users. |
internalKey | string | Optional client-supplied external reference / idempotency key. When present, lets external systems correlate platform-side records back to their own source-of-truth ids. Not persisted to a column — populated by the request handler when the caller sets it. |
__objectType | string | Discriminator string (entity class short-name) emitted alongside the id in serialized output. Resolved at read time by `getObjectType()`; lets the FE dispatch entity-specific rendering without inspecting the URL. |
id | bigint | Snowflake-style primary key (unsigned BIGINT). Generated by `IdFactory` at create time; surfaced to the FE / API as a `G`-prefixed string and stripped back to plain bigint server-side before Doctrine lookup. |
createdDate | integer | Unix timestamp the row was first persisted. Set in the entity's PrePersist hook; never rewritten on subsequent updates. |
updatedDate | integer | Unix timestamp the row was last touched. Bumped on every commit that hits the Doctrine UoW for this entity; drives FE invalidation + the listing change cursor. |
passiveUpdatedDate | int | Read-through alias for `updatedDate` exposed under different serializer groups. Lets the FE distinguish "real edit" from "background touch" projections without changing the underlying column. |
listingUpdatedDate | int | Listing-projection timestamp surfaced only under the `listMode` group. Driven by `TripCache` and other listing-shape refreshers separately from `updatedDate` so a listing rebuild doesn't trigger detail-page invalidation. |