Architecture
Baudflow is a Phoenix 1.8 + LiveView app backed by PostgreSQL and Oban. The work flows through a four-stage pipeline, each stage in its own worker, triggered by Oban jobs and never reaching into another stage’s internals.
The pipeline
SchedulerWorker (per minute — thin dispatcher)
│
▼
SpeedtestWorker (run the Ookla CLI, stream NDJSON, insert a Measurement)
│
├─▶ BenchmarkWorker (evaluate health)
└─▶ NotificationWorker (alert on degradation)
CleanupWorker (prunes by retention, on its own schedule)
- Decide → Run → Evaluate → Notify. Each stage is decoupled and passes through Oban jobs or context APIs.
- SpeedtestWorker owns binary resolution, timeout wrapping, NDJSON parsing, and insertion — the speedtest binary is never invoked anywhere else.
Contexts
DB access is routed exclusively through three contexts, each owning one domain:
Baudflow.Measurements— schema, NDJSON streaming worker, scheduler, cleanupBaudflow.Runs— test-run trackingBaudflow.Settings— typed runtime configuration
Repo and import Ecto.Query live only inside context files.
Real-time updates
LiveViews subscribe to the single "measurements" PubSub topic. Events have
stable shapes, and a terminal event is emitted for every outcome so the UI never
waits on a timer. Throughput is always displayed in bits/sec (the raw
bandwidth field is bytes/sec and storage-only).
Endpoints
GET /health— lightweight liveness check for uptime monitors.GET /metrics— Prometheus text format, hand-rolled with no cache; exposesbaudflow_*gauges (NaN for nil values).