/api/status/public live?Status: Accepted Date: 2026-04-28 UTC Refs: #601, #581, status-raxx-app.md
status.raxx.app requires a backend that serves /api/status/public — the JSON feed consumed by the public status page React app. Three candidate homes were evaluated:
raxx-api-prod Heroku dyno — the existing backend_v2/ Flask app already has a /api/status/ namespace for operator use. Adding a /api/status/public route is one blueprint addition.raxx-status-prod — a new Heroku dyno running a thin Flask subset, isolated from the trading API.The public endpoint is read-only and unauthenticated. It does not execute trades, access PII, or write any state. Its primary quality requirement is availability: the status page must be reachable even when the trading API is degraded.
Cloudflare Worker for the public-facing /api/status/public JSON endpoint.
The status page is the surface users check when something is wrong. Cohosting the status endpoint on the dyno being monitored creates a availability paradox: if raxx-api-prod is down, the status endpoint reporting it is also down. A Worker breaks that dependency — it runs at the Cloudflare edge, has no shared blast radius with Heroku, and its global PoP deployment means read latency is low without any additional caching configuration.
The Worker's data source is a Postgres-backed state table (see status-raxx-app.md §3) that the polling worker writes to. The Worker reads this table via a connection-pooled query or via a lightweight internal Flask endpoint on raxx-api-prod that the Worker calls with an internal API key. The Worker response is cached at the edge with Cache-Control: public, max-age=60 for the surfaces list and max-age=300 for the incidents log.
Internal operator endpoints (/api/status/ — full probe data, audit log, FreeScout webhook receiver) remain on raxx-api-prod. The Worker only serves the projection defined in the public API contract.
Positive:
- Availability boundary: public status endpoint is decoupled from the Heroku dyno's health. CF network uptime (99.99%+) is independent of Heroku uptime.
- Free tier capacity: Cloudflare Workers free tier (100k req/day) covers current and projected public traffic comfortably without incremental cost.
- Edge caching: 60-second max-age means the Worker rarely calls the upstream data source. Cache invalidation on state change is possible via CF Cache API from the webhook receiver.
- No new Heroku dyno or ops overhead.
Negative:
- New deployment unit: the Worker is a separate deployable from backend_v2/. Feature-developer needs a wrangler.toml and a workers/status-public/ directory. This is a modest ops addition.
- Internal API key required: the Worker must authenticate to its data source. This key lives in CF Worker environment secrets (not in code). It must be rotatable without Worker redeployment (CF secrets are set via Wrangler and take effect on next request without redeploy).
- Worker cold-start latency is negligible for V8 isolates but relevant if the Worker is paused due to zero traffic (never a problem for a public status page with organic traffic).
Alternatives Rejected:
raxx-api-prod: Rejected because the blast radius is shared. A Heroku dyno restart, a memory ceiling breach, or a bad deploy puts the status endpoint offline at the moment it is most needed.workers/status-public/ at repo root.GET /internal/status/snapshot on raxx-api-prod with header X-Status-Worker-Key: <secret>. That secret is in Infisical at /raxx/status-worker/internal-key and in CF Worker secrets as STATUS_WORKER_INTERNAL_KEY.POST /internal/status/invalidate on the Worker (CF Cache API purge) is called by the FreeScout webhook receiver after a state write — ensuring the status page reflects ticket changes within the 5-minute SLA.Access-Control-Allow-Origin: https://status.raxx.app on all responses.