Transit captures public GTFS and GTFS-Realtime feeds, keeps the raw bytes, normalizes and analyzes them in PostgreSQL, then publishes versioned JSON snapshots that a public dashboard reads through Cloudflare. This page shows the moving parts and how data crosses them.

Reference Value
Subject and boundary Whole-system context, runtime components, end-to-end data flow and the boundaries every change must respect. Detailed behavior lives on the linked leaves.
Verified source Repository tree at main 9733eb26d92533f56cdc8bc46b81b93fbb5987c8, checked November 10, 2026.
Support state Implemented source and tracked configuration. Live runtime state is not asserted here; see ‣.

Context

flowchart LR
  A[STM and OC Transpo<br/>GTFS, GTFS-RT, STM i3 alerts] -->|"STM vehicles 20 s, trip updates 30 s, alerts 300 s<br/>OC Transpo 30 s, no alerts"| W[Realtime worker<br/>VM, Docker Compose]
  A -->|daily| J[Scheduled jobs<br/>GitHub Actions]
  W --> B[(Bronze R2<br/>raw objects)]
  J --> B
  W --> P[(PostgreSQL 16 + PostGIS<br/>raw, core, silver, gold)]
  J --> P
  W -->|live tier| S[(Snapshot R2<br/>/v1 contract)]
  J -->|static and historic tiers| S
  S --> D[data.yesid.dev<br/>R2 custom domain]
  S --> X[transit-data-proxy Worker<br/>/data/* and /api/v1/*]
  D --> U[Browser]
  X --> U
  S -->|SNAPSHOTS binding| WEB[transit-web Worker<br/>SvelteKit SSR + assets]
  WEB --> U
  U -->|address lookup| GEO[transit-web<br/>/api/geocode]
  GEO --> EXT[geolocator.api.geo.ca]

Components

Component Runs on Owns Source
Realtime worker Compose services worker (STM) and octranspo-worker (OC Transpo) on a Linux VM, tracked in the repository Compose file. Production runs them from the VM's Compose override Realtime and alert capture, Silver load, Gold projection, best-effort live publication docker-compose.yml, orchestration.py
Pruner Compose services pruner (STM) and octranspo-pruner (OC Transpo), tracked and run the same way Bounded Silver and Gold retention, independent of capture success cli.py run-pruner-loop
Health API and Caddy Compose services health, caddy (loopback by default) /health report and /health/live liveness health/app.py
PostgreSQL + PostGIS Compose service postgres (Dockerfile.postgis, PostgreSQL 16) Relational truth behind the public boundary 0093 baseline through 0096 provider live policy
Scheduled jobs GitHub Actions, ubuntu-24.04 Static pipeline, warm rollups, historic publication, retention, freshness probe, worker start probe, GC marks, basemap refresh .github/workflows
Bronze store Cloudflare R2 (transit-raw in workflow configuration) Raw captures (replay source) and logical database backups settings.py
Snapshot store Cloudflare R2, bound as SNAPSHOTS (transit-snapshots) and served at data.yesid.dev The public /v1 files storage.py
Data proxy Cloudflare Worker transit-data-proxy Same-origin snapshot delivery and the per-provider KPI endpoint worker.js
Web app Cloudflare Worker transit-web with Static Assets SvelteKit dashboard in English and French apps/web

Address search

The browser sends address queries to Transit's own /api/geocode endpoint; the geocoder forwards query text with local context and language to geolocator.api.geo.ca. Same-origin provenance checks, bounded input, a validated provider and rate limiting guard that path; results are filtered to the provider's bounds and returned with private, no-store. The local fallback rate limiter is per Worker isolate, not a global quota. Security details: Security and access.

Data flow

Step Owner Result
1. Capture transit_ops.ingestion Raw feed bytes in Bronze with SHA-256, plus a raw.ingestion_runs lineage row
2. Normalize transit_ops.silver Static GTFS datasets, thin realtime snapshots, GIS and alert history
3. Analyze transit_ops.gold Facts, marts, five-minute and hourly delay summaries, daily warm rollups
4. Publish transit_ops.snapshots Gated JSON files per provider and tier under /v1
5. Serve R2, transit-data-proxy Cached, range-capable public reads; no database access
6. Present apps/web Validated reads, filters, honest absence states, maps and charts

Boundaries that hold everywhere

Read next

Question Page
Where does a change belong? ‣
How does capture through Gold work? ‣
What is in the public contract? Snapshot publication and public contract
How is it deployed and run? ‣ · ‣

Support boundaries

The public app runs SvelteKit 3 with eight shared-design packages pinned to v0.40.0 (#738, main 6b5a9c80). Eligible content sections start expanded on a first visit, with the bulk control labelled Collapse all; the bulk choice persists in sections-choice, the TOC card starts open, and independent/map tools are outside the bulk action. Shared boot recovery exposes pending content if initialization fails or stalls. Public web /health is a versioned snapshot-read check, separate from the VM health API and feed freshness. GitHub issues plus owner mention/assignment carry failures; application logs omit invocation records and redact queries.