Build a Last-Mile Delivery Tracking System
distributed-systems scalability performance
System Design Deep Dive
Live Delivery Tracking System
Turn noisy phone GPS into a smooth dot and an ETA that doesn’t lie, for thousands of drivers at once.
Picture a marathon broadcast trying to track ten thousand runners with nothing but a stopwatch and a pair of binoculars. Every few seconds a spotter catches a glimpse of a runner’s bib number through the crowd, jots down where they were standing, and has to guess both how fast that runner is actually moving and when they will cross the next mile marker, even though the glimpse itself is imprecise, the runner might have ducked behind a water station, and by the time the spotter’s radio call reaches the broadcast booth, the runner has already moved somewhere else entirely.
That is the shape of the problem underneath last-mile delivery tracking, except the runners are drivers, the glimpses are GPS pings arriving every few seconds from a phone bouncing around in a cupholder, and the audience is not one broadcast booth but hundreds of thousands of customers each watching a single driver’s dot crawl across their own screen in real time. A driver’s phone reports its own noisy estimate of where it is, that estimate needs to be cleaned up and pinned to the actual road network, an ETA has to be recomputed continuously as traffic and remaining distance change, and the result has to reach the customer’s app the moment it changes, not the next time the customer happens to refresh.
A naive version of this looks deceptively simple: store the driver’s raw latitude and longitude, compute a straight-line distance to the destination, divide by an average speed, and have the customer’s app poll a REST endpoint every few seconds for the latest numbers. That falls apart on contact with reality. Raw GPS coordinates drift by tens of meters near tall buildings and inside parking garages, so a straight rendering of raw pings makes the delivery dot visibly teleport across buildings and jump backward across intersections it never crossed. Straight-line distance ignores that roads bend, that a highway on-ramp adds distance a bird’s-eye line does not see, and that traffic on one road can be crawling while a parallel road two blocks over is empty. And polling does not scale gracefully: at hundreds of thousands of concurrent trackers, even a modest poll interval means tens of thousands of requests per second hitting a stateless read endpoint for information that mostly has not changed since the last poll.
We need to solve for three things simultaneously: turning a noisy, occasionally out-of-order stream of raw GPS pings into a smooth, road-accurate position signal; recomputing an ETA against live traffic conditions that is honest about its own uncertainty instead of pretending to a precision it cannot support; and pushing state changes to the customer the instant they happen over a connection that stays open, rather than making every customer’s app ask over and over whether anything is new.
Requirements and Constraints
Functional Requirements
- Ingest GPS location pings from each driver’s mobile app roughly every 3 to 5 seconds for the duration of an active delivery
- Smooth raw, noisy GPS coordinates and map-match them onto the underlying road network, so the rendered position tracks an actual street rather than empty space or the inside of a building
- Maintain an explicit state machine for every delivery (
assigned,en_route_to_pickup,arrived_at_pickup,picked_up,en_route_to_dropoff,arriving,delivered,failed) and reject illegal state transitions - Recompute each active delivery’s ETA on a regular cadence and immediately after a significant deviation, using live traffic conditions rather than static historical averages alone
- Express every ETA as a confidence band (for example, 12 to 16 minutes) rather than a single number, widening the band when the underlying signal is less certain
- Push location and ETA updates to the customer’s app over a persistent connection the moment something meaningfully changes, with no polling required
- Sequence every ping and state event correctly per delivery even when the network delivers them out of order or the driver app retries a send
- Retain full location and event history per delivery for support investigations, delivery disputes, and offline analytics
Non-Functional Requirements
- Scale: 50,000 concurrent active deliveries at peak, each driver pinging roughly every 4 seconds, for a sustained ingestion rate near 12,500 pings/sec, bursting toward 20,000 pings/sec during regional demand spikes
- Customer fan-out: up to 200,000 concurrent customer WebSocket connections at peak, since a delivery is often watched by more than one viewer (customer app plus a support dashboard)
- Ingestion latency: p99 under 250ms from a raw ping leaving the driver’s device to a smoothed, map-matched position being available to downstream consumers
- Push latency: under 2 seconds end to end, from a driver’s raw ping to the corresponding update rendering on the customer’s screen
- ETA recompute cadence: at least once every 15 seconds per active delivery, and immediately on a significant route or traffic deviation
- Durability: at-least-once ingestion with idempotent processing; no ping is silently and permanently lost even if it arrives duplicated or out of order
- Availability: 99.95% for the ingestion and push path; on partial failure the system serves the last known good location and ETA rather than showing nothing
- Retention: a full year of ping and event history per delivery for analytics and dispute resolution, with older raw pings eligible for downsampling
Constraints and Assumptions
- We assume the driver’s mobile app already owns GPS hardware access and reports pings in a standard schema; we do not design the device-level location API integration
- We assume turn-by-turn route geometry between two points comes from an external routing and mapping provider; “distance remaining along the route” is treated as a lookup against that provider’s data, not something this system computes from raw map tiles
- We assume live traffic conditions are supplied by a third-party traffic feed that reports a congestion factor per road segment; we consume that feed, we do not build the sensor network or the traffic model behind it
- Driver-to-delivery assignment, deciding which driver is offered which delivery, is owned by a separate dispatch and matching service; this system starts once a delivery is already assigned to a driver
High-Level Architecture
The system has six major components: the GPS Ingestion Gateway, the Location Smoothing and Map-Matching Service, the Driver and Delivery State Machine, the ETA Recalculation Engine, the Delivery Event Sequencer, and the WebSocket Fan-out Gateway.
The GPS Ingestion Gateway is the front door for every raw ping: it validates the payload, rejects pings whose reported accuracy is too poor to trust, and deduplicates retried sends using a per-delivery device sequence number. The Location Smoothing and Map-Matching Service takes a validated ping and turns it into a stable, road-accurate position, first smoothing the raw coordinate with a motion model and then snapping the result onto the correct road segment. The Driver and Delivery State Machine is the source of truth for where a delivery sits in its lifecycle, from assigned through delivered, and it is the only place that lifecycle state actually changes. The ETA Recalculation Engine combines the smoothed position, the remaining route geometry, and a live traffic feed to produce an ETA expressed as a confidence band rather than a single number. The Delivery Event Sequencer takes every state change, location update, and ETA update and imposes a strict per-delivery order on them before anything is treated as final, since the network and the driver app’s retry logic do not guarantee order on their own. The WebSocket Fan-out Gateway holds a live subscription per delivery from every customer app and support dashboard watching it, and pushes an update only when something worth showing has actually changed.
A ping’s life looks like this: the driver’s app sends a raw coordinate, the Ingestion Gateway validates and deduplicates it, and the Smoothing and Map-Matching Service turns it into a clean position pinned to a real road. That position feeds two things in parallel: the Driver and Delivery State Machine, which checks whether this position implies a lifecycle transition (arriving at the pickup address, for instance), and the ETA Recalculation Engine, which combines the position with the live traffic feed to produce an updated ETA range. Both the state change and the ETA update are handed to the Delivery Event Sequencer, which applies them in the correct order even if they arrive out of sequence, and only then does the WebSocket Fan-out Gateway decide whether the net effect is worth pushing to the customer’s screen.
The single most important architectural decision is decoupling how often a driver’s phone reports its position from how often the customer’s screen updates. Ingestion runs on the driver’s own cadence, every few seconds; ETA recompute runs on a cadence bounded by the traffic feed’s freshness; and the WebSocket push only fires when a meaningful-change filter decides something worth showing has actually changed. Coupling all three to the same clock either floods a customer’s mobile connection with noise or starves the tracking view of updates exactly when something important happens between ticks.
Component Deep Dives
The GPS Ingestion Gateway
This component’s job is to accept a flood of raw GPS pings from thousands of driver devices, reject the ones that cannot be trusted, and guarantee that a duplicate or out-of-order retry is never applied twice.
The obvious assumption, that pings arrive once, in order, and roughly on time, does not hold on a mobile network. Phones lose signal in tunnels and parking structures, buffer pings locally, and flush a burst of them the moment connectivity returns; flaky cellular connections cause the same ping to be retried by the client before an acknowledgment comes back. Treating every inbound payload as new and authoritative would let a retried ping double-count a driver’s movement, and a batch of delayed pings flushing out of order could make the smoothing filter downstream briefly believe the driver teleported.
We accept a ping only if its reported accuracy radius is tight enough to be useful and its device-assigned sequence number is strictly greater than the last one accepted for that delivery. The sequence number, not a timestamp, is what protects against duplicates and reordering, because a device’s own clock can be skewed or wrong in ways a monotonic per-delivery counter is not.
# GPS ping ingestion: validation, dedup, and out-of-order rejection
# Demonstrates: idempotent handling of retried/duplicate pings using a
# per-delivery monotonic device sequence number, not wall-clock time alone
from dataclasses import dataclass
from typing import Optional
@dataclass
class RawPing:
delivery_id: str
driver_id: str
device_seq: int # monotonic counter set by the driver app, resets per delivery
lat: float
lng: float
accuracy_m: float # GPS accuracy radius reported by the device
client_ts_ms: int
MAX_ACCEPTABLE_ACCURACY_M = 100.0
MAX_CLOCK_SKEW_MS = 30_000
class PingIngestor:
def __init__(self, seq_store):
self.seq_store = seq_store # last accepted device_seq per delivery_id
def accept(self, ping: RawPing, server_ts_ms: int) -> Optional[RawPing]:
if ping.accuracy_m > MAX_ACCEPTABLE_ACCURACY_M:
return None # too imprecise to trust, drop before it pollutes smoothing
skew = abs(server_ts_ms - ping.client_ts_ms)
if skew > MAX_CLOCK_SKEW_MS:
ping.client_ts_ms = server_ts_ms # do not trust an unreliable device clock
last_seq = self.seq_store.get(ping.delivery_id, -1)
if ping.device_seq <= last_seq:
return None # duplicate or out-of-order retry, already applied or superseded
self.seq_store.set(ping.delivery_id, ping.device_seq)
return ping
Think of this like a mail sorting facility that recognizes a letter it already sorted yesterday because of a duplicate tracking label, and sets aside a letter whose address is illegible rather than guessing where to route it. What breaks without the sequence check: a retried ping replaying an old position would look like a legitimate new sample to every downstream consumer, and the smoothing filter would interpret the sudden jump backward as real, unnecessary movement, momentarily distorting both the rendered position and the velocity estimate it depends on.
This is the same idea behind idempotent producers in Kafka, where each producer attaches a monotonically increasing sequence number per partition so the broker can silently drop a retried, already-committed write instead of accepting it twice. Delivery telemetry SDKs from companies like Uber and DoorDash use the same trick at the client, tagging every location sample with a per-trip sequence number rather than relying on the device clock alone.
Location Smoothing and Map-Matching
This component’s job is to turn a jittery raw coordinate into a stable position that actually sits on a road, using both the physics of how a vehicle moves and the topology of the street network.
Trusting a single raw GPS sample is like trying to read someone’s handwriting through a shaky camera: no individual frame is reliable, so instead you keep a running estimate of where the pen tip actually is, based on where it has been and how fast it was moving, and only nudge that estimate toward each new noisy frame rather than replacing it outright. We keep a running position-and-velocity estimate per delivery using a constant-velocity Kalman filter, predicting forward from the last known state and then correcting that prediction against each new ping, weighted by how much that particular ping’s own reported accuracy says it should be trusted.
# 2D constant-velocity Kalman filter for GPS location smoothing
# Demonstrates: turning noisy raw lat/lng pings into a smooth position + velocity estimate
import numpy as np
class LocationKalmanFilter:
def __init__(self, initial_lat: float, initial_lng: float):
# State: [lat, lng, lat_velocity, lng_velocity]
self.x = np.array([initial_lat, initial_lng, 0.0, 0.0])
self.P = np.eye(4) * 1e-4 # initial state covariance
self.Q = np.eye(4) * 1e-8 # process noise (how much we trust the motion model)
self.H = np.array([[1, 0, 0, 0], [0, 1, 0, 0]]) # we only observe position, not velocity
def predict(self, dt_seconds: float) -> None:
F = np.array([
[1, 0, dt_seconds, 0],
[0, 1, 0, dt_seconds],
[0, 0, 1, 0],
[0, 0, 0, 1],
])
self.x = F @ self.x
self.P = F @ self.P @ F.T + self.Q
def update(self, lat: float, lng: float, accuracy_m: float) -> tuple[float, float]:
# A looser GPS accuracy means a larger measurement covariance, so a jumpy
# low-accuracy ping pulls the estimate less than a tight, confident one.
r = max(accuracy_m / 111_320.0, 1e-6) ** 2 # meters -> approx degrees, squared
R = np.eye(2) * r
z = np.array([lat, lng])
y = z - self.H @ self.x
S = self.H @ self.P @ self.H.T + R
K = self.P @ self.H.T @ np.linalg.inv(S)
self.x = self.x + K @ y
self.P = (np.eye(4) - K @ self.H) @ self.P
return float(self.x[0]), float(self.x[1])
A smoothed point still is not enough, because it can land on a sidewalk, a parking lot, or the wrong side of a divided highway. We take that smoothed point and map-match it against the small set of road segments nearby, scoring each candidate by both its distance from the point and how closely its heading matches the driver’s recent direction of travel, with a bonus for staying on the same segment the driver was already matched to a moment ago.
# Simplified map-matching: snap a smoothed GPS point onto the road network
# Demonstrates: candidate scoring by distance + heading consistency, not just
# "closest road segment", which prevents snapping across a divided highway
from dataclasses import dataclass
import math
@dataclass
class RoadSegment:
segment_id: str
start_lat: float
start_lng: float
end_lat: float
end_lng: float
heading_deg: float
def project_to_segment(lat: float, lng: float, seg: RoadSegment) -> tuple[float, float, float]:
# Approximate planar projection (fine at city-block scale); returns
# (projected_lat, projected_lng, distance_meters)
ax, ay = seg.start_lng, seg.start_lat
bx, by = seg.end_lng, seg.end_lat
px, py = lng, lat
dx, dy = bx - ax, by - ay
seg_len_sq = dx * dx + dy * dy
t = 0.0 if seg_len_sq == 0 else max(0.0, min(1.0, ((px - ax) * dx + (py - ay) * dy) / seg_len_sq))
proj_x, proj_y = ax + t * dx, ay + t * dy
dist_deg = math.hypot(px - proj_x, py - proj_y)
return proj_y, proj_x, dist_deg * 111_320.0
def match_point(
lat: float, lng: float, heading_deg: float,
candidates: list[RoadSegment], previous_segment_id: str | None,
) -> RoadSegment:
def score(seg: RoadSegment) -> float:
_, _, dist_m = project_to_segment(lat, lng, seg)
heading_diff = min(abs(heading_deg - seg.heading_deg), 360 - abs(heading_deg - seg.heading_deg))
continuity_bonus = -15.0 if seg.segment_id == previous_segment_id else 0.0
# Lower is better: distance dominates, heading mismatch and segment
# continuity are tie-breakers that prevent snapping across a median.
return dist_m + (heading_diff * 0.5) + continuity_bonus
return min(candidates, key=score)
The property that makes the Kalman filter safe to run unattended at scale is that it weighs each new ping by its own reported accuracy rather than trusting every sample equally. A ping reported with 80 meters of accuracy nudges the estimate gently; a ping reported with 5 meters of accuracy is allowed to correct it firmly. That single weighting rule is what keeps one bad urban-canyon sample from yanking the displayed position across the map.
What would break if you skipped map-matching entirely and rendered the smoothed point directly: a smoothed position can still legitimately sit a few meters off the actual road centerline, which is invisible on a highway but glaring on a dense city block, rendering the delivery dot inside a building footprint or straddling a property line, and it gives the ETA engine no clean notion of “which road segment, at what remaining distance” to reason about.
A common mistake is tuning the Kalman filter’s process noise once and leaving it fixed for every kind of movement. A process noise tuned for steady highway driving lags noticeably behind a real turn in a dense city grid, because the filter keeps trusting its straight-line prediction over the new samples telling it the vehicle actually turned. Production systems widen the process noise dynamically when recent heading changes are large, trading a little smoothness for responsiveness exactly when the driver is maneuvering.
This pairing, a Kalman-style motion filter feeding a Hidden-Markov-style map matcher, is close to the approach described in Microsoft Research’s widely cited map-matching paper by Newson and Krumm, and it is the same shape of pipeline behind consumer-facing GPS fusion in Google Maps and OSRM-based routing engines: never trust a single raw sample, and never render a position without checking it against what the road network actually allows.
The Driver and Delivery State Machine
This component’s job is to hold the one authoritative answer to “what stage is this delivery in right now” and to refuse any transition that skips a stage or moves backward.
The tempting shortcut is to infer delivery state purely from proximity: if the driver’s position is within a small radius of the pickup address, call it arrived_at_pickup; if it is within a radius of the dropoff address, call it delivered. That collapses the moment GPS drift or a large parking lot puts the driver’s smoothed position just outside the radius while they are, in fact, standing at the counter, or just inside it while they are actually idling at a nearby coffee shop. A pure geofence has no memory and no business context, so it flip-flops a delivery’s displayed state back and forth every time the driver’s position wobbles near the radius boundary.
We model the lifecycle as an explicit state machine, where location proximity is a strong hint but the actual transition is confirmed by a driver action (an app button tap) or a corroborating business rule (a scan event at pickup), and every transition is validated against the delivery’s current state before it is accepted.
// Delivery state machine: validates transitions and rejects illegal jumps
// Demonstrates: a driver app or dispatcher cannot skip states or move backward,
// which is what keeps the customer-facing timeline trustworthy
package delivery
import "fmt"
type State string
const (
Assigned State = "assigned"
EnRouteToPickup State = "en_route_to_pickup"
ArrivedAtPickup State = "arrived_at_pickup"
PickedUp State = "picked_up"
EnRouteToDropoff State = "en_route_to_dropoff"
Arriving State = "arriving"
Delivered State = "delivered"
Failed State = "failed"
)
var allowedTransitions = map[State][]State{
Assigned: {EnRouteToPickup, Failed},
EnRouteToPickup: {ArrivedAtPickup, Failed},
ArrivedAtPickup: {PickedUp, Failed},
PickedUp: {EnRouteToDropoff, Failed},
EnRouteToDropoff: {Arriving, Failed},
Arriving: {Delivered, Failed},
Delivered: {},
Failed: {},
}
func Transition(current State, next State) (State, error) {
for _, allowed := range allowedTransitions[current] {
if allowed == next {
return next, nil
}
}
return current, fmt.Errorf("illegal transition: %s -> %s", current, next)
}
This is the same discipline as a shipping manifest that only lets a package move forward through customs stages: every other system that needs to know “has this delivery already been picked up” reads the manifest, it never re-derives the answer from raw location data itself. What breaks without an explicit machine: two components independently guessing at delivery state from slightly different geofence radii can disagree with each other, so the customer’s app might show picked_up while the driver’s own dispatch view still shows arrived_at_pickup, and there is no single record either one can be checked against.
The most common mistake here is trusting geofence proximity as the sole trigger for a transition, with no dwell time or hysteresis. A driver’s smoothed position wobbling a few meters across a geofence boundary near the destination can otherwise cause the delivery to flip between en_route_to_dropoff and arriving several times in a row, each flip generating its own event and its own customer-facing push. Requiring a short dwell time inside the geofence, or a driver-confirmed action, before committing the transition removes the thrashing.
The ETA Recalculation Engine
This component’s job is to combine a delivery’s smoothed position, its remaining route, and live traffic conditions into an ETA that is honest about how sure it is, not a single number pretending to a precision the input data cannot support.
A ship’s captain does not tell passengers “we dock at 4:12pm,” they say “we expect to dock between 4:00 and 4:30, depending on the tide,” because pretending to a precision the conditions do not support erodes trust the first time the estimate is wrong. Giving a customer a single-number ETA computed from a historical average speed makes the same mistake: during rush hour it is confidently wrong, and confidently wrong is worse for trust than visibly uncertain.
We compute expected travel time per remaining road segment using that segment’s free-flow speed adjusted by a live congestion factor from the traffic feed, then widen or narrow the band around that expected value using a variance ratio observed historically per road class, since a residential street with stop signs and pedestrians has much more variable travel time than a highway.
# ETA recalculation with live traffic weighting and a confidence band
# Demonstrates: turning remaining route distance into a time range, not a
# single fake-precise number, by tracking historical variance per road class
from dataclasses import dataclass
@dataclass
class RouteSegmentRemaining:
length_m: float
road_class: str # 'highway', 'arterial', 'residential'
free_flow_speed_kmh: float
live_speed_factor: float # 1.0 = free flow, 0.4 = heavy congestion, from traffic feed
# Historical p10/p90 speed variance ratio, observed offline per road class.
# Wider variance on residential streets (stop signs, pedestrians, parking) than highways.
SPEED_VARIANCE_RATIO = {
"highway": 0.12,
"arterial": 0.22,
"residential": 0.35,
}
def eta_with_confidence(segments: list[RouteSegmentRemaining]) -> tuple[float, float, float]:
expected_seconds = 0.0
low_seconds = 0.0
high_seconds = 0.0
for seg in segments:
effective_speed_kmh = max(seg.free_flow_speed_kmh * seg.live_speed_factor, 3.0)
expected = seg.length_m / (effective_speed_kmh * 1000 / 3600)
variance = SPEED_VARIANCE_RATIO.get(seg.road_class, 0.25)
low_seconds += expected * (1 - variance)
high_seconds += expected * (1 + variance)
expected_seconds += expected
return expected_seconds, low_seconds, high_seconds
The property that makes this band useful rather than just decorative is that its width tracks empirically observed variance per road class, not a fixed padding slapped on every ETA. A downtown residential street automatically gets a wider band than a highway, without anyone hand-tuning per city or per neighborhood, because the variance ratio was learned from historical travel-time spread, not guessed.
What would break if you skipped the confidence band and shipped a single number instead: the ETA looks precise right up until traffic changes underneath it, and a customer who watched “8 minutes” silently become “14 minutes” trusts the next ETA less than one who was told “8 to 13 minutes” from the start and watched it settle within that range.
Uber’s publicly described DeepETA system predicts a distribution over arrival time rather than a point estimate, surfacing something close to a confidence interval instead of a single number, and Google Maps has long shown a range for “typical traffic” alongside its point estimate. Both are the same underlying admission: travel time is a distribution, and pretending otherwise just moves the error from the estimate to the user’s trust in it.
Delivery Event Sequencing
This component’s job is to guarantee that every state change, location update, and ETA update for a given delivery is applied in the correct order, even when the network delivers them out of sequence or a client retries a send.
Ordering by arrival time at the server is tempting and wrong, because two events for the same delivery can be processed by different workers, retried at different times, or delayed by an unlucky network hop, so “the order the server happened to receive them in” is not the same as “the order they actually occurred in.” We attach a monotonic per-delivery sequence number to every event at the point it is generated, and hold events in a small per-delivery buffer until every earlier-numbered event has already been applied.
// Delivery event sequencer: buffers out-of-order events per delivery and
// applies them in strict sequence before anything reaches the WebSocket fan-out
// Demonstrates: a small reorder buffer with a bounded wait, not an unbounded queue
package sequencing
import "sync"
type Event struct {
DeliveryID string
Seq int64
Payload []byte
}
type Sequencer struct {
mu sync.Mutex
nextSeq map[string]int64
pending map[string]map[int64]Event
apply func(Event)
}
func NewSequencer(apply func(Event)) *Sequencer {
return &Sequencer{
nextSeq: make(map[string]int64),
pending: make(map[string]map[int64]Event),
apply: apply,
}
}
func (s *Sequencer) Ingest(e Event) {
s.mu.Lock()
defer s.mu.Unlock()
expected := s.nextSeq[e.DeliveryID]
if e.Seq < expected {
return // stale duplicate, already applied
}
if s.pending[e.DeliveryID] == nil {
s.pending[e.DeliveryID] = make(map[int64]Event)
}
s.pending[e.DeliveryID][e.Seq] = e
for {
next, ok := s.pending[e.DeliveryID][expected]
if !ok {
break
}
s.apply(next)
delete(s.pending[e.DeliveryID], expected)
expected++
}
s.nextSeq[e.DeliveryID] = expected
}
This is the same discipline a post office uses when it holds parcel number 7 until parcels 1 through 6 have already gone out for delivery, even if parcel 7 physically arrived at the depot first. What breaks without it: a location update processed ahead of the picked_up state change it logically follows could show a moving delivery dot before the customer’s own app even knows the delivery has started, and a delayed arrived_at_pickup event landing late could regress the displayed status backward after the customer already saw en_route_to_dropoff.
The property that makes per-delivery sequencing tractable at this scale is that delivery_id is effectively a partition key: ordering only ever needs to be enforced within one delivery’s own event stream, never across deliveries. That turns a global ordering problem into thousands of small, independent, cheaply bounded ordering problems running in parallel.
An unbounded reorder buffer is a memory leak waiting to happen. If a sequence number is lost forever, a driver’s app crashes before a retry, a device is swapped mid-delivery, the naive version of this sequencer holds every later event for that delivery in memory indefinitely, waiting for a gap that will never fill. Production systems bound the wait with a timeout, forcibly release the buffered events past that timeout with an explicit gap marker, and flag the delivery for reconciliation rather than let one stuck delivery grow its buffer forever.
This is the same ordering guarantee Kafka gives within a single partition: strict order is only promised per partition key, never across the whole topic, which is exactly why picking delivery_id as the partition key here is what makes the guarantee cheap to provide.
The WebSocket Fan-out Gateway
This component’s job is to hold a live, persistent connection per delivery watcher and push an update only when something worth showing has actually changed, without flooding a customer’s phone or draining its battery.
Pushing every raw ping straight to the customer’s screen is the same mistake as a doorbell that rings continuously instead of only when someone is actually at the door: most of that signal is noise the customer’s app has to receive, parse, and render for no visible benefit, and on a weak cellular connection it competes with the updates that actually matter. We publish a location and ETA update to a delivery’s subscribers only when the position has moved past a small distance threshold or the ETA has shifted by more than a small time threshold since the last thing we sent.
// WebSocket fan-out: pushes an update only when location or ETA changed
// enough to matter, keyed per delivery
package fanout
import (
"encoding/json"
"math"
"sync"
)
type LocationUpdate struct {
DeliveryID string
Lat, Lng float64
ETALowSec int
ETAHighSec int
}
const minMeaningfulMoveMeters = 15.0
const minMeaningfulETADeltaSec = 30
type Hub struct {
mu sync.RWMutex
subscribers map[string]map[chan []byte]bool
lastSent map[string]LocationUpdate
}
func (h *Hub) Publish(update LocationUpdate) {
h.mu.Lock()
defer h.mu.Unlock()
last, seen := h.lastSent[update.DeliveryID]
if seen && !meaningfulChange(last, update) {
return // nothing worth pushing to a battery-powered phone over cellular
}
h.lastSent[update.DeliveryID] = update
payload, _ := json.Marshal(update)
for ch := range h.subscribers[update.DeliveryID] {
select {
case ch <- payload:
default:
// Slow consumer: drop this frame rather than block the whole hub;
// the next meaningful update will supersede it anyway.
}
}
}
func meaningfulChange(last, next LocationUpdate) bool {
distMoved := haversineMeters(last.Lat, last.Lng, next.Lat, next.Lng)
etaDelta := math.Abs(float64(next.ETALowSec - last.ETALowSec))
return distMoved >= minMeaningfulMoveMeters || etaDelta >= minMeaningfulETADeltaSec
}
func haversineMeters(lat1, lng1, lat2, lng2 float64) float64 {
const earthRadiusM = 6371000.0
toRad := func(deg float64) float64 { return deg * math.Pi / 180 }
dLat := toRad(lat2 - lat1)
dLng := toRad(lng2 - lng1)
a := math.Sin(dLat/2)*math.Sin(dLat/2) +
math.Cos(toRad(lat1))*math.Cos(toRad(lat2))*math.Sin(dLng/2)*math.Sin(dLng/2)
c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
return earthRadiusM * c
}
What breaks without the slow-consumer guard in that code: a single customer connection on a poor network, one that cannot drain its channel fast enough, would otherwise block the entire hub’s publish path for every other subscriber, turning one weak cellular connection into an outage for every other delivery sharing that hub instance.
Trading platforms apply the identical filter to market data fan-out, pushing a price update to subscribers only past a minimum tick size rather than on every underlying quote change, for exactly the same reason: most consumers of a live feed care about meaningful state changes, not the full-resolution noise underneath them.
Data Model
The data model spans five entities: drivers and their live state, deliveries and their current lifecycle stage, GPS pings, sequenced delivery events, and ETA snapshots kept for accuracy auditing.
-- Deliveries: the customer-facing unit of work and its current lifecycle stage
CREATE TABLE deliveries (
delivery_id BIGINT PRIMARY KEY,
driver_id BIGINT REFERENCES drivers(driver_id),
customer_id BIGINT NOT NULL,
status TEXT NOT NULL DEFAULT 'assigned'
CHECK (status IN ('assigned', 'en_route_to_pickup', 'arrived_at_pickup',
'picked_up', 'en_route_to_dropoff', 'arriving',
'delivered', 'failed')),
pickup_lat NUMERIC(9,6) NOT NULL,
pickup_lng NUMERIC(9,6) NOT NULL,
dropoff_lat NUMERIC(9,6) NOT NULL,
dropoff_lng NUMERIC(9,6) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
delivered_at TIMESTAMPTZ
);
CREATE INDEX ON deliveries (driver_id) WHERE status NOT IN ('delivered', 'failed');
CREATE INDEX ON deliveries (customer_id, created_at DESC);
-- Drivers: live operational state, read on every ping and ETA recompute
CREATE TABLE drivers (
driver_id BIGINT PRIMARY KEY,
active_delivery_id BIGINT,
last_lat NUMERIC(9,6),
last_lng NUMERIC(9,6),
last_heading_deg NUMERIC(5,2),
last_ping_at TIMESTAMPTZ,
connection_status TEXT NOT NULL DEFAULT 'offline'
CHECK (connection_status IN ('online', 'offline', 'stale'))
);
-- GPS pings: high-volume, append-only, partitioned by day for cheap retention/expiry
CREATE TABLE gps_pings (
delivery_id BIGINT NOT NULL,
device_seq BIGINT NOT NULL,
raw_lat NUMERIC(9,6) NOT NULL,
raw_lng NUMERIC(9,6) NOT NULL,
smoothed_lat NUMERIC(9,6),
smoothed_lng NUMERIC(9,6),
matched_segment_id TEXT,
accuracy_m NUMERIC(6,2) NOT NULL,
client_ts TIMESTAMPTZ NOT NULL,
server_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (delivery_id, device_seq)
) PARTITION BY RANGE (server_ts);
CREATE TABLE gps_pings_2026_07_05 PARTITION OF gps_pings
FOR VALUES FROM ('2026-07-05') TO ('2026-07-06');
CREATE INDEX ON gps_pings (delivery_id, server_ts DESC);
-- Delivery events: append-only sequenced log, the source of truth for state changes
CREATE TABLE delivery_events (
id BIGSERIAL PRIMARY KEY,
delivery_id BIGINT NOT NULL REFERENCES deliveries(delivery_id),
sequence_no BIGINT NOT NULL,
event_type TEXT NOT NULL
CHECK (event_type IN ('state_change', 'location_update', 'eta_update', 'exception')),
payload JSONB NOT NULL,
occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX ON delivery_events (delivery_id, sequence_no);
-- ETA snapshots: one row per recompute, kept for accuracy auditing and model tuning
CREATE TABLE eta_snapshots (
id BIGSERIAL PRIMARY KEY,
delivery_id BIGINT NOT NULL REFERENCES deliveries(delivery_id),
computed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
eta_low_seconds INT NOT NULL,
eta_high_seconds INT NOT NULL,
remaining_meters NUMERIC(10,2) NOT NULL,
traffic_factor_avg NUMERIC(4,3)
);
CREATE INDEX ON eta_snapshots (delivery_id, computed_at DESC);
gps_pings is partitioned by day, so retention and downsampling of old pings is a matter of dropping or rewriting whole partitions rather than deleting rows one at a time. delivery_events is unique on (delivery_id, sequence_no), which is the same invariant the Delivery Event Sequencer enforces in memory, backed here so a replay or a reconciliation job can never insert the same sequence number twice. drivers.last_lat, last_lng, and last_ping_at are kept in a small, hot, frequently updated table separate from the much larger historical gps_pings log, since the dispatch and re-routing paths only ever need a driver’s current position, never their full history.
A ping enters as raw_lat/raw_lng, gets a smoothed_lat/smoothed_lng and matched_segment_id filled in by the Location Smoothing and Map-Matching Service, and its downstream effects, a possible state transition and a fresh ETA snapshot, are recorded as their own rows rather than overwriting anything. If the meaningful-change filter decides a given update is not worth pushing, the underlying rows are still written; only the WebSocket push is skipped, which is what lets a support engineer later reconstruct exactly what happened on a delivery even if the customer’s screen never visibly moved at that moment.
Sharding gps_pings or delivery_events by driver_id would optimize for “show me one driver’s full shift history,” but the dominant read pattern during an active delivery is “give me this one delivery’s ordered timeline right now,” scoped by delivery_id. Partitioning gps_pings by time for retention, and indexing everything else by delivery_id, keeps the hot path fast without needing a driver-scoped index at all.
Key Algorithms and Protocols
Kalman Filter Location Smoothing
Covered in the Location Smoothing and Map-Matching section above, the constant-velocity Kalman filter runs in constant time per update, O(1) against a fixed four-dimensional state, regardless of how long a delivery has been running.
The property that makes this filter safe to run unattended across tens of thousands of deliveries at once is that each update’s correction strength is driven entirely by the incoming ping’s own reported accuracy, so no separate per-delivery or per-city tuning pass is needed to keep one bad sample from overcorrecting the estimate.
A meaningful edge case: a driver boarding a ferry or a train mid-delivery moves at a speed and in a way the constant-velocity motion model does not expect, producing a run of large prediction residuals in a row. Production systems watch for a sustained residual spike and reset the filter’s covariance rather than let it keep fighting a motion model that no longer fits.
Map-Matching by Candidate Scoring
Covered in the same section, matching a point to a road segment runs in O(c) time, where c is the small number of candidate segments within a fixed search radius of the point, typically single digits in dense areas and effectively zero extra cost anywhere else.
The property that makes greedy candidate scoring reliable instead of merely fast is the continuity bonus toward the previously matched segment. Without it, a point sitting almost equidistant between two parallel roads flickers between them ping to ping; with it, the matcher only switches segments when the new evidence is strong enough to overcome a small bias toward staying put.
An edge case worth naming: a driver executing a tight U-turn or backing into a driveway can briefly make the continuity bonus stick to the wrong segment, since the heading used for scoring lags a sharp maneuver by a sample or two. Production map-matchers bound how many consecutive pings the continuity bonus can win before forcing a fresh, unbiased re-evaluation.
ETA Confidence Band Computation
Covered in the ETA Recalculation Engine section above, this computation is linear, O(n) in the number of remaining route segments, aggregating an expected time and a low/high band per segment into a total for the rest of the trip.
The property that makes this band trustworthy is that variance is tracked per road class rather than as one global padding factor. A ten-segment route through a mix of highway and residential streets ends up with a band that reflects where the actual uncertainty lives, rather than a flat percentage applied uniformly regardless of road type.
An edge case: if the driver deviates from the originally computed route, the remaining-segment list itself is stale, so the engine has to re-fetch remaining route geometry from the routing provider before the next recompute rather than continuing to sum distances along a path the driver is no longer following.
Per-Delivery Event Sequencing
Covered in the Delivery Event Sequencing section above, applying an in-order event is O(1) amortized; buffering an out-of-order event and later draining a run of now-contiguous events costs O(w), where w is the depth of the temporary gap, bounded by the sequencer’s wait timeout.
The property that keeps this scheme’s memory bounded is that every delivery eventually terminates, reaching delivered or failed, at which point its sequencing state can be evicted entirely. Without that eviction, a system running for months would accumulate sequencing state for every delivery that ever existed, most of which will never receive another event.
Scaling and Performance
The GPS Ingestion Gateway and the WebSocket Fan-out Gateway are the two components under the most sustained load, and they scale along two different axes: ingestion scales by geography, since drivers, road segments, and the traffic feed are all naturally regional, while fan-out scales by delivery identity, since a customer’s connection only ever needs updates for the one delivery they are watching.
Capacity Estimation:
Given:
- 50,000 concurrent active deliveries at peak
- Each driver pings every 4 seconds -> ~12,500 pings/sec sustained,
bursting to ~20,000 pings/sec during regional demand spikes
- Raw ping payload ~150 bytes; smoothed + map-matched row ~200 bytes
- ETA recompute cadence: every 15 seconds per active delivery
- Up to 200,000 concurrent customer WebSocket connections
(roughly 4 watchers per delivery on average, app + support tooling)
Ingestion bandwidth:
12,500 pings/sec * 150 bytes = ~1.9 MB/sec sustained raw ingest
Burst: 20,000 pings/sec * 150 bytes = ~3.0 MB/sec
ETA recompute load:
50,000 deliveries / 15 sec per recompute = ~3,333 recomputes/sec
~2ms compute per recompute = ~6.7 CPU-seconds/sec of steady load
10-12 worker cores gives comfortable headroom for bursts after
traffic-feed refreshes land for many deliveries at once
GPS ping storage (before downsampling):
12,500 pings/sec * 86,400 sec/day * ~120 bytes/row = ~130 GB/day raw
A full year of raw retention at that rate is untenable; downsampling
pings older than 30 days to one sample per 30 seconds cuts cold
storage roughly 8x versus keeping every raw ping indefinitely
WebSocket fan-out:
Meaningful-change filtering cuts ~12,500 pings/sec down to roughly
30-40% actually triggering a push, ~4,000-5,000 pushes/sec fanned
out across up to 200,000 connections, ~200 bytes per push,
~1 MB/sec of aggregate outbound push bandwidth
The dominant bottleneck is not raw compute, it is keeping ingestion and fan-out capacity matched to where drivers and customers actually are, since demand is never evenly spread across geography. Sharding the Ingestion Gateway by region, the same regional boundaries the traffic feed and routing provider already use, means a busy city center becomes a hot shard that can be split further, rather than an unpredictable function of which drivers happen to be active. Sharding the WebSocket Fan-out Gateway by a consistent hash of delivery_id keeps each delivery’s subscribers pinned to one owning node regardless of where in the world the customer’s app happens to be, which avoids a cross-region hop on every single push.
Caching matters most on the read side of fan-out: each gateway node keeps the last-sent snapshot per delivery in memory, keyed by delivery_id, so a customer’s app reconnecting after a brief network drop gets an immediate catch-up push from cache instead of waiting for the next natural ping to arrive. Write traffic dominates on the ingestion side, twelve thousand pings a second landing continuously, while read traffic dominates on reconnect and cold-start paths, which is why the two sides of the system are cached and scaled independently rather than sharing one general-purpose data store.
This mirrors how ride-hailing and delivery platforms like Uber shard real-time location processing by geographic cell, using schemes like S2 or H3 hexagonal cells rather than driver ID, so a hot city center becomes a shard that can be split further on its own, instead of hot load being an unpredictable function of which driver IDs happen to be active at a given moment.
Failure Modes and Recovery
| Failure | Detection | Impact | Recovery |
|---|---|---|---|
| Driver phone loses GPS signal (tunnel, parking garage) | No ping received within the expected interval, heartbeat timeout on the driver connection | Delivery dot freezes, ETA goes stale | Dead-reckon the position forward from last known speed and heading for a bounded window, mark the location “stale as of Xs ago” in the UI beyond that window |
| Duplicate or out-of-order pings from client retry logic | Per-delivery device sequence number check on ingestion | Could regress the smoothed position backward or double-count movement | Idempotent sequence check drops any ping whose device_seq is not strictly greater than the last accepted one |
| Customer WebSocket connection drops (app backgrounded, network blip) | Missed WebSocket ping/pong heartbeat | Customer stops receiving live updates until reconnect | On reconnect, gateway serves the last known good snapshot from its in-memory cache immediately, then resumes live pushes |
| Live traffic feed provider outage or stale data | Feed timestamp freshness check against a max staleness threshold | ETA falls back to free-flow speed estimates, less accurate under real congestion | ETA Recalculation Engine automatically widens the confidence band and flags the snapshot as low-confidence when the traffic feed is stale |
| Delivery Event Sequencer buffer stuck on a missing sequence number | Buffer age for a pending gap exceeds a bounded wait timeout | Later events for that delivery never release, buffer memory grows unbounded for that delivery | Force-release buffered events past the timeout with an explicit gap marker in the event log, flag the delivery for reconciliation |
| Map-matching snaps to the wrong parallel road (divided highway, service road) | Sudden segment change inconsistent with recent heading and implausible implied speed | Wrong road class feeds the ETA engine, producing a visibly wrong estimate | Heading-based continuity bonus toward the previous segment, plus rejecting a candidate segment if it implies a physically impossible speed jump |
The most common operational mistake is treating a frozen delivery dot as a system failure and forcing a full state refresh or a customer-facing error. In the overwhelming majority of cases it is a driver’s phone temporarily out of GPS signal in a tunnel or a parking structure, and the correct behavior is graceful dead-reckoning plus a visible “last seen Xs ago” indicator, not discarding state and starting over as if the delivery itself had failed.
Comparison of Approaches
| Approach | Latency to customer | Complexity | Failure mode | Best fit |
|---|---|---|---|---|
| Client polls a REST endpoint every 5-15s | Bound by poll interval, seconds of staleness | Low | Wasted requests at scale, most polls return unchanged data | Low-traffic internal tools, not consumer-facing tracking |
| Server-Sent Events (SSE), push every raw ping | Sub-second | Medium | One-directional only, and pushing unfiltered noise wastes bandwidth and battery | Simpler read-only dashboards with modest connection counts |
| WebSocket push, unfiltered (every raw ping forwarded) | Sub-second | Medium | Floods weak mobile connections, drains battery, renders a jumpy unsmoothed dot | Rarely justified once smoothing already exists upstream |
| WebSocket push with meaningful-change filtering (this design) | Near-real-time, bounded by filter thresholds | Medium-high | Requires careful threshold tuning, too tight wastes bandwidth, too loose feels laggy | Consumer-facing live tracking at this scale |
| Long-polling REST | Seconds, bound by request timeout and reopen delay | Medium | Holds a connection open per client without true bidirectional push, still round-trips per update | Environments where WebSocket support is unavailable or blocked |
We would pick WebSocket push with meaningful-change filtering for any consumer-facing tracking product at this scale, because it is the only approach on this list that gets both a persistent, low-latency channel and a filter that keeps that channel from being wasted on noise the customer cannot use. Polling and long-polling both trade latency for simplicity in a way that stops working once hundreds of thousands of customers are watching at once, unfiltered push trades bandwidth and battery life for a small implementation simplification that is not worth it once smoothing already exists upstream, and SSE gives up the bidirectional channel a tracking app eventually wants for things like a customer tapping “message the driver” over the same connection.
Key Takeaways
- GPS pings must be deduplicated and sequenced by a device-assigned counter, not a timestamp. Device clocks drift and skew in ways a monotonic per-delivery sequence number does not.
- A Kalman filter that weighs each ping by its own reported accuracy is what keeps one bad urban-canyon sample from yanking the displayed position across the map. Trusting every sample equally is the more common and more fragile mistake.
- Map-matching needs heading and continuity, not just distance, to pick the right road segment. Distance alone confuses parallel roads and divided highways.
- An explicit delivery state machine, confirmed by driver action rather than inferred purely from geofences, prevents a delivery’s displayed status from flickering as GPS drift crosses a proximity boundary.
- ETA should be a confidence band whose width tracks historically observed variance per road class, not a single number padded by a fixed percentage. A wrong-but-precise ETA damages trust faster than a visibly uncertain one.
- Per-delivery event sequencing turns a global ordering problem into thousands of small, independent, cheaply bounded ones.
delivery_idis effectively a partition key for ordering guarantees. - WebSocket push only pays off when paired with a meaningful-change filter. Pushing every raw ping is functionally the same mistake as polling too aggressively, just moved to the other side of the connection.
- Ingestion scales by geography and fan-out scales by delivery identity, and they should be sharded independently along those two different axes, not forced into a single general-purpose sharding scheme.
The counter-intuitive lesson is that the parts of this system that sound the most like plain infrastructure work, deduplication, sequencing, and a meaningful-change filter, are what actually make the fancier parts, the Kalman filter and the traffic-aware ETA model, trustworthy in production. A perfectly tuned smoothing filter fed duplicate or out-of-order pings still produces a wrong answer; the unglamorous plumbing is what the interesting algorithms depend on to see clean, correctly ordered data in the first place.
Frequently Asked Questions
Q: Why not just render raw GPS coordinates directly instead of running them through a Kalman filter and map-matching pipeline?
A: Raw GPS coordinates drift by tens of meters near tall buildings, inside parking structures, and under tree cover, which is invisible on a highway but glaring on a dense city block, rendering the delivery dot inside a building or straddling the wrong side of the street. A Kalman filter turns a noisy sequence of samples into a stable position-and-velocity estimate, and map-matching pins that estimate onto an actual road segment, which is also what gives the ETA engine a clean notion of remaining distance to reason about, not a scattering of raw points a routing calculation cannot use directly.
Q: Why WebSocket instead of simply having the customer’s app poll a REST endpoint every few seconds?
A: Polling at hundreds of thousands of concurrent trackers means tens of thousands of requests per second hitting a stateless endpoint for information that mostly has not changed since the last poll, and it caps latency at the poll interval no matter how fast the underlying data actually changes. A persistent WebSocket connection lets the server push the instant something meaningful changes and lets the meaningful-change filter suppress everything else, which is strictly better on both latency and wasted bandwidth once you already have to build the filter for other reasons.
Q: Why express ETA as a confidence band instead of a single number, when customers presumably want one clear answer?
A: A single number implies a precision the underlying traffic and route data cannot actually support, and it is confidently wrong the moment conditions change, which damages trust more than a range that turns out to be correct. A band whose width reflects real historical variance per road class gives the customer an honest answer that is more likely to still be true a few minutes later, and it degrades gracefully, the band simply widens, when the input signal itself is less certain.
Q: Why sequence events by a per-delivery counter instead of relying on server-received timestamps, since the server could just process things in the order it saw them?
A: The order the server happens to receive events in is not the same as the order they actually occurred in, because retries, network hops, and worker scheduling can all reorder messages in flight. A monotonic per-delivery sequence number assigned at the point an event is generated is the only signal that reliably reflects true event order, and buffering briefly until any preceding sequence numbers arrive is what prevents a delayed event from silently corrupting the customer-visible timeline.
Q: How does the system handle a driver’s phone losing GPS signal entirely, like inside a tunnel or a large parking garage?
A: The absence of pings past the expected interval is itself the signal: the system dead-reckons the displayed position forward briefly using the driver’s last known speed and heading, and once that grace window expires, it marks the position explicitly stale in the UI rather than silently continuing to guess or freezing without explanation. That is a deliberate degrade-gracefully choice, a clearly labeled stale position is more useful to a customer than either a frozen dot with no explanation or a guess presented as fact indefinitely.
Q: Why not compute ETA purely from historical average speeds instead of depending on a live, third-party traffic feed?
A: Historical averages are a fine fallback but a poor primary signal, because they cannot see today’s accident, today’s road closure, or this specific hour’s unusually heavy congestion, which is exactly the information that makes an ETA useful in the moment rather than merely plausible on average. The design already falls back to free-flow, historically informed speeds and a wider confidence band when the live feed is stale or unavailable, so historical data is not discarded, it is demoted to a fallback rather than promoted to the primary source.
Interview Questions
Q: Walk through what happens to a single GPS ping from the moment it leaves a driver’s phone to the moment a customer’s screen updates.
Expected depth: Cover ingestion validation and sequence-number deduplication, Kalman filter predict-and-update against the device’s reported accuracy, map-matching against nearby road segments with a continuity bonus, the parallel branch into the state machine and the ETA engine, sequencing the resulting events by delivery_id, and the meaningful-change filter deciding whether the WebSocket fan-out actually pushes anything. Discuss where the 250ms ingestion and 2-second end-to-end latency budgets get spent across those stages.
Q: How would you decide the thresholds for the meaningful-change filter in the WebSocket fan-out layer, and what happens if you get them wrong?
Expected depth: Discuss the tradeoff between a threshold too tight, which wastes bandwidth and battery pushing updates no human perceives as meaningful, and a threshold too loose, which makes the tracking view feel laggy or stuck despite the driver actually moving. Talk about tuning distance and ETA-delta thresholds against real usage data rather than guessing, and why the thresholds might reasonably differ between dense urban delivery and long highway hauls.
Q: A customer reports that their delivery driver’s dot appeared to teleport several blocks in an instant. How would you debug this?
Expected depth: Walk through checking the raw ping accuracy and Kalman filter residuals around that timestamp, whether map-matching snapped to a discontinuous road segment inconsistent with heading, whether the device sequence number check let a stale, out-of-order ping through, and whether the WebSocket fan-out’s meaningful-change filter pushed an update built from a bad intermediate state. Emphasize using the retained gps_pings history, including matched_segment_id, to reconstruct exactly what the pipeline saw.
Q: How would you redesign the ETA engine if the live traffic feed provider had a multi-hour outage during peak demand?
Expected depth: Discuss the fallback path to historical free-flow speeds per road class, automatically widening the confidence band to reflect the reduced confidence, and flagging affected ETA snapshots as low-confidence for downstream consumers and analytics. Cover why this should degrade gracefully rather than fail closed, since a wider, less certain ETA is still more useful to a customer than no ETA at all.
Q: The system needs to support ten times the current number of concurrent deliveries. What breaks first, and how would you address it?
Expected depth: Point to the WebSocket Fan-out Gateway’s per-node connection and cache memory as one likely early bottleneck, and the GPS Ingestion Gateway’s per-region shard capacity as another. Discuss sharding fan-out further by a finer-grained consistent hash of delivery_id, splitting hot geographic ingestion shards along the same regional boundaries the traffic feed already uses, and why the Delivery Event Sequencer’s per-delivery, per-partition-key design means it scales by adding more parallel shards rather than needing a fundamentally different ordering scheme.
Premium Content
Unlock the full article along with everything else in the archive — all in one place.