How Real-Time Bus Arrival Works: GPS Drift, ETA Accuracy, and 100K QPS Reads
For anyone building location-aware, high-write, high-read systems, the article delivers a production-grade pattern for turning noisy GPS streams into stable predictions while absorbing 100K QPS reads. The practical techniques - hash-tagged Lua scripts, Kalman-baseline ETA, hysteresis state machines, and cache-breakdown defenses - transfer directly to ride-hailing, delivery tracking, or any IoT telemetry platform.
The article walks through the entire architecture behind a bus app's "2 stops, about 5 minutes" message. Key decisions are driven by scale: 30,000 vehicles writing 3,000-6,000 GPS reports per second, while peak read QPS reaches 100K inside a first-tier city. Writes are buffered through Kafka and processed in Flink, which cleans raw GPS, projects positions onto a route model, and computes ETA. Everything about the data model avoids the common mistake of using straight-line distance; instead, a dist_from_start field in the route-stop table lets ETA be computed as a simple subtraction along the route.
The write path tackles GPS drift with wild-point filters, coordinate system conversion between WGS84 and GCJ-02, and a timestamp-version Lua optimistic lock for out-of-order idempotency. Arrival judgment uses a hysteresis dual-threshold state machine to prevent fence-edge flicker. ETA prediction evolves from a naive distance/speed formula to a segmented baseline plus real-time correction, then to a three-layer weighted speed model, and finally to a Kalman increment correction that only adjusts a bias coefficient per vehicle, converging as the bus approaches. Flink implements this with keyed state and only predicts the next 3-10 stops.
For reads, the system uses a Caffeine local cache, Redis, and a Lua batch query on a ZSET whose score is the vehicle's distance along the route. SingleFlight and logical expiration protect against cache breakdown, while aggressive degradation rules mean availability beats accuracy: better to show a timetable estimate than a white screen. The push side aggregates subscribers by line+stop to cut a million-user push down to a few thousand channel broadcasts. Storage follows a hot/warm/cold three-tier separation to keep billions of trajectory records affordable.
The most common misunderstanding in real-time bus systems is treating vehicles as "nearby points" with Redis GEO; the actual core is a distance-along-route model because buses travel fixed lines.
The article's ETA evolution shows that rule-based statistical baselines quickly get error down from 180s to 28s, and a Kalman correction adds stability without requiring heavy ML, which is a pragmatic path for production.
Availability is explicitly prioritized over accuracy: the design accepts eventual consistency and 3-second delays as long as the UI never shows a white screen, a tradeoff that matches real user tolerance for transit data.
The single most transferable pattern is using a ZSET score as the vehicle's route-distance, which turns a multi-step query into one Lua script - a clean example of pushing computation into the data store.
The article's advice to "quantify first, then design" is not just interview advice; the specific QPS/TPS estimates shape every subsequent choice, from Kafka partition keys to cache TTLs.
What's more reasonable is to not have the onboard terminal at all [grin][grin][grin]