Scaling
What’s built and verified here vs. the production plan for the parts that need real infra.
Telemetry pipeline
Section titled “Telemetry pipeline”- Downsampling (built):
services/aggregation.downsample()rolls raw samples into hourlytelemetry_aggregates(count + supply avg/min/max). Runs on the worker on a schedule; tested. - Retention (built):
apply_retention(raw_max_age_days)drops raw rows past a cutoff once aggregated, so history survives compactly as aggregates; tested. - Partitioning (plan): in production, make
telemetrya time-partitioned table — native Postgres declarativePARTITION BY RANGE (ts)with monthly partitions (viapg_partman), or a TimescaleDB hypertable. This keeps inserts and recent-range queries on small partitions and makes retention a cheapDROP PARTITION. Not applied to the dev table here (it would destabilize the test fixtures); it’s a forward migration at deploy time. The(device_id, ts)index already supports the access pattern. - Ingest buffer (plan, optional): for very large fleets, put a queue (Redis Streams / Kafka / managed) in front of the DB writer so spikes don’t backpressure devices; the store-and-forward buffer already lives on the agent, so brief backend unavailability never drops data.
Horizontal scaling
Section titled “Horizontal scaling”The API is stateless (JWT, no server-side session), so it scales by adding replicas behind a
load balancer — demonstrated in docs/loadtest-report.md (4 workers ≈ 4× a single worker, ~3,900
buildings within SLO on one host; add hosts for more). Caveats tracked in the security backlog: the
rate limiter and Prometheus metrics are per-instance — move the limiter to a shared store and scrape
each replica. Background work (downsample, retention, weather, alert eval) runs on a separate worker
pool (arq/Celery + Redis) that scales independently.
Throughput & limits
Section titled “Throughput & limits”Per-IP rate limiting sheds abuse; per-org plan entitlements cap fleet size commercially. For very large orgs, add per-device ingest rate caps and a 429 backoff the agent already honors (it buffers).
SLOs & error budgets
Section titled “SLOs & error budgets”- Ingest: p95 < 500 ms, error rate < 1% (load-test SLO, currently PASS).
- Availability: target 99.9% on
GET /health; the building’s heat is not affected by platform downtime (controllers run locally), so the error budget is about visibility/ops, not safety. - Burn-rate alerts on the error budget via the metrics in Phase 10.
Cost monitoring
Section titled “Cost monitoring”Track DB storage growth (retention bounds it), egress, worker minutes, and SIM data (Integrations). Tie spend dashboards to the managed-platform billing API; alert on anomalies.
Staged fleet OTA (built)
Section titled “Staged fleet OTA (built)”services/ota + api/ota_admin: publish a version, then a rollout reaches a deterministic
stage_percent slice of the fleet (each device hashes to a stable 0–99 bucket). Advance 10 → 50 →
100 to expand the cohort monotonically; pause to halt. Devices pull their target from
GET /ota/latest. Tested. Real signed/verified package serving + rollback on the device is Phase 4
(hardware).