Skip to content

Surge Pricing

Taxi & Private HireProductsSurge › 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.

Fare Base fare€12.00 Surge locked at quote +€3.00 Total€15.00 · its own charge line · won't move on recompute · capped at 2× the fare
The uplift is a first-class line on the charge, fixed at quote time and platform-capped — no surprises, no drift.

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.

OFF no surge · the default SHADOW records what it would charge · never bills ON bills + funds the pool validate for weeks before a customer pays a cent
A safety-first rollout per company and fleet — nothing bills real money by accident.

The uplift is shaped by the detection curve and funds the driver pool.

Settings

How operators configure this feature.

Surge pricing

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

Fields

FieldTypeDescription
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.