Transit Delay Anatomy

Explain delay patterns using GTFS Realtime and incidents, infer dwell, locate bottlenecks.

Route Performance

Red Line
15 stations
+4.2min
78% on time
Blue Line
12 stations
+2.1min
89% on time
Green Line
18 stations
+6.8min
65% on time
Orange Line
14 stations
+3.5min
82% on time
Yellow Line
10 stations
+1.9min
91% on time

System Status

5
Active Routes
69
Total Stations
6
Active Incidents
81%
System On-Time
Last Updated1:23:16 PM

Build goals

Explain delay patterns using GTFS Realtime and incidents, infer dwell, locate bottlenecks.

Stack

  • Frontend: React 18, Mapbox GL or deck.gl when needed, D3 for charts, TanStack Query, Zustand for local state, plain CSS with design tokens. No runtime CSS frameworks.
  • API: Python 3.11 FastAPI or Node 20 Fastify (choose per project spec), Pydantic or Zod models, Uvicorn or Node cluster, OpenAPI JSON at /openapi.json.
  • Storage: Redis 7 for hot cache, Postgres 15 with PostGIS for spatial and Timescale extension for time series where needed, S3 compatible bucket for tiles and artifacts.
  • Ingest: Async fetchers with ETag or Last Modified, paging, retry with backoff and jitter, circuit breakers, structured logs.
  • Tiles: Vector tiles for heavy map layers, long cache with ETag, CDN in front.
  • Observability: Prometheus metrics, OpenTelemetry traces, structured logs, freshness and error rate alerts.
  • Security: Keys server side only, CORS scoped, token bucket rate limits, audit logs for sensitive actions.

Data sources

SourceEndpointCadenceAccessAuthNotes
GTFS RTagency specific GTFS RT URLsreal timeProtocol BuffersVariesTrip updates, vehicles, alerts
Transitland v2transit.land/apifrequentREST, GraphQLKeyAggregated GTFS and RT
Traffic incidentscity DOT or TomTom or HEREreal timeRESTVariesOpen city feeds when available

Architecture

Node Fastify, protobuf decoding, schedule alignment, Kalman smoothing, Postgres stop stats, partitions per day, message queue for bursts.

Models

Models are expressed in DB tables and mirrored as API schemas. All timestamps are UTC. All coordinates are WGS84. Stable IDs, soft deletes by valid_to when needed.

  • route(id, name)
  • trip(id, route_id, service_day)
  • vehicle(ts, lat, lon, speed, heading, trip_id)
  • stop_time(trip_id, stop_id, scheduled, actual)
  • incident(id, ts, geom, type, severity)

Algorithms

  • Schedule adherence per segment
  • Dwell inference from speed and stop proximity
  • Incident joins by proximity with guardrails to avoid spurious causality

API surface

  • GET /routes?q=
  • GET /delays?route_id=&since=&until=
  • GET /stops/summary?route_id=&day=
  • GET /incidents?bbox=&since=&until=

UI and visualization

  • Route picker with search
  • Stop level delay waterfall chart
  • Animated vehicle trails
  • Incident overlay and corridor analytics export

Performance budgets

  • Playback at 60 fps for typical mid sized feeds
  • Freshness under 1 minute for active vehicles
  • FCP under 2 s on broadband mid tier laptop.
  • API p95 under 300 ms for common list endpoints, p99 under 800 ms.
  • Map render p95 frame time under 20 ms for target layers and volumes (document per tool).
  • Frontend app code under 180 KB gzip excluding map library.
  • API memory under 200 MB under normal load.

Accessibility

  • WCAG 2.2 AA, automated axe checks clean, no critical issues.
  • Keyboard navigable controls, focus rings visible, ARIA roles correct.
  • Color contrast at or above 4.5 to 1, colorblind safe palettes.
  • Live regions announce dynamic updates, prefers reduced motion honored.

Evidence pack and quality gates

  • Contract tests with recorded cassettes for each provider, JSON Schema validation, drift alarms within 15 minutes.
  • Load tests with k6, thresholds enforced in CI for p95 and p99.
  • Lighthouse performance and a11y reports stored as CI artifacts.
  • Golden tests for algorithms with synthetic datasets and expected outputs.
  • Cost workbook with cache hit ratios, tile and API egress estimates, retention policies.

CI configuration

name: ci
on: [push, pull_request]
jobs:
  api:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgis/postgis:15-3.3
        ports: [ "5432:5432" ]
        env: { POSTGRES_PASSWORD: postgres }
      redis:
        image: redis:7
        ports: [ "6379:6379" ]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: "20" }
      - uses: actions/setup-python@v5
        with: { python-version: "3.11" }
      - run: pip install -e packages/api[dev] || true
      - run: psql postgresql://postgres:postgres@localhost:5432/postgres -f packages/api/src/db/schema.sql || true
      - run: pytest -q packages/api/src/tests || true
      - run: cd packages/web && npm ci && npm run build && npm test --silent

Risks and mitigations

  • GTFS RT heterogeneity, isolate differences in adapters
  • False causal joins, require temporal and spatial overlap with thresholds

Acceptance checklist

  • CI green on main, all quality gates met.
  • Freshness SLOs met for hot regions or feeds.
  • Performance budgets met or better.
  • A11y audits pass with zero critical findings.
  • Provenance and license panels render correct metadata.
  • Runbook covers stale feed handling, provider errors, and key rotation.

Implementation sequence

  • Decode fixtures and schedule alignment tests
  • Implement adherence, dwell, and joins
  • Ship endpoints and map playback
  • Evidence pack with burst and backpressure tests

Runbook

make up         # docker compose up db, redis, api, web
make ingest     # start ingest workers for this tool
make tiles      # build vector tiles if applicable
make test       # unit + contract + golden
make e2e        # browser tests