AC Transit Board of Directors · Briefing
An independent, real-time performance tracker built entirely from the agency's own public data — and what it shows about the service we actually deliver.
This briefing has three parts: why I built this system, how it works, and a walk-through of what it shows — followed by a short closing thought on what a transit agency's product really is.
It started as a personal annoyance. The official AC Transit app often shows arrival predictions and bus locations that don't match what's actually happening on the street. The usual culprit is how vehicles get registered by dispatch and operations: the app can confidently predict a bus that isn't really coming, while the bus that is coming goes unrecognized.
So I built a simple live map. It reads the agency's own GTFS‑Realtime feed directly — the same public data stream the official app is built on — and plots the real vehicles operating on a route. When I'm standing at a stop wondering "is my bus actually coming?", I can look at the real positions and decide for myself.
From what I can tell, the official app doesn't consume the agency's standard GTFS‑Realtime feed. Instead it calls AC Transit's ActRealtime prediction service (see api.actransit.org/transit/Help), with requests shaped roughly like this:
GET actrealtime/prediction?stpid={stpid}&rt={rt}&vid={vid}&top={top}&tmres={tmres}&callback={callback}&showocprd={showocprd}
That prediction is keyed on a vehicle being correctly registered in several ways by dispatch and the operator (vehicle ID, run, assignment, and so on). When any piece of that registration is missing or wrong — which, as far as I can tell, happens fairly often — the prediction binds to the wrong vehicle or to none at all, and the rider is shown a bus that isn't really coming.
GTFS‑Realtime is far less brittle. So long as the vehicle is simply registered to its route (e.g. the on-vehicle headsign/display is set correctly), it is at least correctly associated with that route. From there I can use the vehicle's reported location to impute arrival accuracy, speed, and everything else — a much higher success rate even when the deeper dispatch registration is incomplete.
| ActRealtime prediction (official app) | GTFS‑Realtime (this tool) | |
|---|---|---|
| Depends on | Full, correct dispatch/operator registration of each vehicle (ID, run, assignment). | The vehicle simply being on the right route, plus a GPS position. |
| Failure mode | A mis-registered vehicle yields wrong or phantom arrivals. | Degrades gracefully — the route association still holds. |
| Net effect | Brittle, and visibly wrong at the stop. | Higher success rate; reliable enough to compute accuracy metrics. |
Then came the bigger realization. To draw that map, I poll the real-time feed every minute for every vehicle in the system. Accumulated over days and weeks, that stream becomes a complete record of where every bus was, minute by minute. From that record I can reconstruct each scheduled trip and measure what riders actually experienced:
The live map grew into a full performance-analytics system — built with no privileged data access. Everything here is computed from feeds AC Transit already publishes. Anything I can measure, the agency can measure too.
The whole thing is a small, serverless pipeline on Google Cloud. It is deliberately cheap and boring to run: there is nothing to babysit, and it costs on the order of a few dollars a month.
A scheduler pings a single small service every minute. That service reads the live feed, figures out where each bus is along its route, detects when it passes each scheduled stop, and stores the results. Static dashboards read those results — no database server to keep running.
/scrape records vehicle positions; /refresh-gtfs ingests the nightly static schedule; /track-performance turns raw positions into per-stop on-time results. Results land in Cloud Storage and BigQuery, which feed the public dashboards.The interesting work happens once a minute. The service takes each vehicle's latest position, projects it onto the shape of the route it's running to get a precise distance-along-route, and watches for the moment that distance crosses each scheduled stop. That crossing is the bus's actual arrival; comparing it to the timetable gives the delay.
Each bus-on-a-trip is followed as a small state machine. While it's running, the system accumulates positions and ticks off stops. A trip is finalized when it reaches its last stop — or, if a bus's GPS goes quiet for 20 minutes, the trip is closed out with whatever was observed and flagged as incomplete. Both outcomes are written to the warehouse.
| Choice | Why it matters for the board |
|---|---|
| Public data only | Built on GTFS‑Realtime + GTFS‑Static, both published by the agency. There is no special access and nothing proprietary — the results are independently reproducible. |
| Rider-centric definitions | A stop counts toward On Time Service Delivered only if the bus arrived between 1 minute early and 7 minutes late. Stops the bus never reached remain in the denominator. This is intentionally stricter than a typical internal on-time metric: a bus running 10 minutes late technically ran its trip, but it did not arrive inside the rider window. |
| Fully auditable | Every raw position is retained, so any figure on a dashboard can be traced to the underlying observations and any individual trip can be replayed minute by minute. |
| Cheap & serverless | ~$6–8/month, no servers held warm, no operations burden. This is a weekend project that runs itself — not a procurement. |
The output is four linked views, each answering a different question — from a one-glance agency report card down to a single stop on a single route.
Every route gets a single letter grade for the last four weeks: a 0–100 composite that blends On Time Service Delivered (60%), on-time rate (15%), speed versus a 13 mph ideal (15%), and headway regularity (10%). The agency-wide grade is shown up top.
A single service day in detail: headline rates, the full minute-by-minute delay distribution, schedule compliance (including dropped and not-completed trips), arrivals by time of day, headway distortion, and a per-route breakdown.
The seven-day rollup is where structure appears: On Time Service Delivered by day, a delay heatmap across day × hour, per-route delay curves through the day, and a route × day grid of schedule compliance. This is where you can see, for example, that the afternoon peak is consistently the system's weakest window.
The deepest view drops onto a single route. Every stop is mapped and colored by how late its worst arrivals run, sized by severity — so a problem segment is visible at a glance. The page also charts passenger wait time (derived from observed headways) and speed by hour and direction.
I'll end where a recent op-ed in Mass Transit magazine (April 14, 2026, "Who should run your transit agency?") lands. Its thesis is simple and, I think, exactly right:
Transit agencies describe themselves as operators, planners, engineers, customer-service organizations, infrastructure managers. But from a rider's perspective, the product is much simpler: a bus or train arrives at a particular place at a particular time.
The schedule determines that product. Everything else exists to support it.
That is precisely what this system measures — the agency's actual product, scored from the rider's side of the windshield, using only data the agency already publishes.
Explore it live: the real-time map and the performance dashboards (report card · daily · weekly · route). Source and architecture notes: github.com/kuanb/actransit_perf_v2.