The real-time sequel to the Cyclistic analysis:
that project studied 6.2M historical rides — this one runs a living pipeline on the same system. Every 30 minutes,
a scheduled job ingests Divvy's live station feed, forces it through five blocking quality gates, transforms it
with SQL, and publishes what you see below. No servers, no cost — engineering in public.
Citywide bikes available, one point per pipeline run.
A rolling 336-run window on a 30-minute schedule. The daily heartbeat — bikes drained by
the morning commute, rebalanced overnight — reads straight off the line. Hosted-runner scheduling is
best-effort, so the window covers a little more than its nominal seven days; the caption below reports
the span actually captured.
02 — BUSIEST DOCKS RIGHT NOW
Where the bikes are, this half-hour.
03 — PIPELINE HEALTH
Every run validates before it publishes.
Five blocking quality gates run on every ingestion. If any gate fails, the run exits non-zero,
nothing is published, and the failure is public in the run log — bad data breaks the pipeline, never the dashboard.
01Ingest. GitHub Actions cron fires every 30 minutes; Python pulls Divvy's GBFS station status and metadata — ~2,000 stations, ~4,000 rows per run.
02Validate. Five blocking gates: station count in range, feed freshness under 30 minutes, join coverage ≥ 99%, no negative counts, citywide totals sane. Fail loud, publish nothing.
03Transform. DuckDB executes the SQL layer — an active-stations view joining both feeds, then citywide KPI and top-station aggregations. Joins live in SQL, not Python loops.
04Publish. Compact JSON artifacts force-pushed as a single commit to a data branch — bounded repo size, served free with CORS. This page fetches them directly; a 7-day rolling window keeps history without growth.