TL;DR: Predict the distribution of travel time, not a single number: serve p50 for the displayed ETA and p90 for any promise (delivery window, "arrive by"), because a mean-accurate ETA is late half the time. Build it as quantile regression over road-segment and route features fused with live traffic, calibrate the quantiles, and close the loop with every completed trip as a fresh label.
How to approach it
The framing move is to refuse the point estimate. An ETA is consumed as a commitment, so the cost of being 5 minutes late is not the cost of being 5 minutes early, and the right object is a predictive distribution you can read quantiles off. Clarify the surface first: a turn-by-turn ETA that updates mid-trip is different from a delivery promise shown once at checkout. Ask what the consumer optimizes (driver routing, courier dispatch, a customer-facing window) because that sets which quantile and how stale the features can be. Then decide segment-level versus route-level composition, name the live and static features, and define both an offline metric and the online guardrail.
A strong answer
Model travel time as quantile regression. Train one model (gradient-boosted trees, or a deep net for the route encoder) with a pinball/quantile loss to emit p50, p90, and p10 jointly. The displayed ETA is p50. Any promise the business is judged on, a DoorDash delivery window or an "arrive by" guarantee, is set near p90 so you are early roughly 90% of the time. Under-promising here is not pessimism, it matches the asymmetric cost: a courier marked late churns a customer, a courier early does not.
The core design tension is segment-level versus whole-route. A route is a sequence of road segments; the naive approach predicts each segment's time and sums them. Per-segment is reusable, cacheable, and composes to any route, but summing independent segment predictions ignores route-level correlation (a storm slows every segment together; turns, merges, and lights between segments add time no single segment owns) and the errors do not add cleanly in quantile space (the p90 of a sum is not the sum of the p90s). The strong design is a hybrid: a base per-segment speed model from the road graph, plus a route-level correction model that takes a route embedding (the segment sequence, number of turns, intersections, road-class transitions) and predicts a residual and the route-level quantile spread. Graph structure matters: segments are nodes and edges in the road network, so a graph neural net or learned segment embeddings capture that a segment's speed depends on its neighbors and feeders.
Features split into three families. Static road features: segment length, road class, speed limit, lane count, number of stop signs and traffic lights, historical speed by time-of-day-of-week (the most powerful single signal). Live traffic features: current observed speed from probe-GPS pings on each segment, incident and closure feeds, weather, and a short-horizon traffic forecast, because for a 40-minute drive you care about the segment's speed when the vehicle arrives there, not now. Trip context: vehicle type (a bike courier and a car compose segments differently), departure time, and for delivery, store prep time and parking/handoff time, which are often the largest variance terms and live outside the road graph entirely.
The label is the actual segment or route traversal time from completed trips, which makes labels essentially free and continuous: every finished trip is a training example with no human annotation. That is the heart of the feedback loop. Mind the survivorship bias: you only observe times for routes drivers actually took, so a route the engine rarely suggests has thin data.
Offline, evaluate per quantile, not with one number. For the median use MAPE and RMSE; for the upper quantile measure calibration, the fraction of trips that finished at or under the predicted p90 (it should be ~90%; if it is 70% your "promise" is late three times as often as advertised). Report by slice: short vs long trips, dense urban vs highway, peak vs off-peak, because a model that is great on highways can be useless downtown. Online, run an A/B and watch outcome metrics, not just error: late-arrival rate against the promised window, customer-reported lateness, and reroute/abandonment. Guardrails that should auto-rollback: a spike in p90 miss rate, a jump in absolute error on any major metro, or display ETAs that flap (a jittery ETA erodes trust faster than a biased-but-stable one), so smooth mid-trip updates and cap how fast the displayed ETA can change.
| Concern | Point-estimate (mean) model | Quantile model |
|---|---|---|
| Display ETA | p50 unavailable; mean is pulled by long tails | p50, robust to tail traffic |
| Delivery promise | Late ~50% of the time by construction | p90, early ~90% of the time |
| What you optimize | Average error | Calibrated coverage at the quantile you serve |
| Failure you cannot see | Asymmetric lateness cost is invisible | Miss rate at p90 is a direct guardrail |
Cold start has two forms. A new road or segment with no traversal history falls back to its road-class prior (speed limit times a class-specific factor) and to neighboring-segment speeds via the graph embedding until trips arrive. A new city leans on the global model plus transfer from similar cities, with city as a feature, and you withhold tight promises (use a wider quantile or a buffer) until local data accumulates. Latency budget is real: route ETA must return inside the routing call, low tens of milliseconds, so per-segment predictions are precomputed and cached on a schedule and only the route-correction head runs at request time.
What interviewers probe next
- "Your p90 is missing 25% of the time." It is miscalibrated, not just inaccurate. Recalibrate the upper quantile on recent held-out trips (the traffic regime drifted), and check whether prep/handoff variance, which lives off the road graph, is the uncaptured term.
- "How do you handle a sudden incident, a crash that just closed a lane?" Live incident and probe-speed features must flow in near-real-time and the in-trip ETA must re-predict, but smooth the update so it does not jump 12 minutes in one tick; a forecasted-speed feature beats reacting only to current speed.
- "Why not just sum per-segment predictions?" It ignores route-level correlation and quantiles do not add, so a route-level correction with a route embedding captures turn/merge time and joint slowdowns the per-segment sum misses.
- "How fresh must the model be?" Per-segment live features update every minute or two; the model retrains hourly to daily. Staleness shows up first as systematic peak-hour bias, so the freshest correctly-calibrated model wins.
Common mistakes
Predicting a single mean and serving it as both the display and the promise, which guarantees the promise is late half the time. Regressing duration from distance and time-of-day with no live-traffic, incident, or weather features, then being shocked it is wrong during rush hour. Summing independent per-segment quantiles as if they were additive. Ignoring the off-graph variance (store prep, parking, handoff) that often dominates a delivery ETA. Reporting one global MAPE while the model is broken in dense downtowns. And treating calibration as optional: an uncalibrated p90 is a number with a decimal point pretending to be a promise.
Key takeaways
- Serve quantiles: p50 for display, p90 for any promise, because asymmetric lateness cost makes a mean-accurate ETA late half the time.
- Use a hybrid of per-segment speed models (cacheable, composable) plus a route-level correction with a route embedding for correlation and quantile spread.
- The label is free: every completed trip is a fresh example, so a fast feedback loop and an hourly-to-daily retrain keep the model calibrated as traffic drifts.
- Evaluate calibration and per-slice error offline, and guardrail the A/B on p90 miss rate and ETA stability, not just average error.
