v0.9.0 — live dashboard updates, in-progress requests, and a quieter poller
Highlights
- The dashboard is live now, not polling-with-extra-steps. A single owner-scoped
SSE endpoint streams in-flight presence and analytics-staleness nudges, so a request
shows up the moment it starts and hands off to its completed row on an explicit event
instead of being inferred from a later poll. Polling remains the reliable core: if the
stream can't be established, is refused, drops, or is buffered by a proxy, the
dashboard falls back to its normal refresh and says Polling instead of Live —
so a blocked deployment is visible rather than silently frozen. - In-progress requests appear on the Overview. The "Recent requests" card now shows
what's still running — model, provider, tier and a live-ticking latency — above the
completed rows, instead of leaving them invisible until they finish. Presence is
tracked in Redis, metadata-only and per-owner; if Redis is unavailable the card simply
shows no live rows. - Per-page icons. Each nav page has a line-icon in the left rail, and the same icon
carries into the page header when you select it — greyscale, following the
single-accent theme. - A much quieter dashboard. It stops polling entirely while its tab is hidden and
refreshes immediately on return; an idle, visible Overview drops from ~40 to ~28
requests/min, and with a connected stream an idle instance costs essentially nothing. - Push can never cost more than the polling it supplements. Nudges are coalesced
server-side and share one refresh budget with the analytics poll, so a burst of
thousands of settled requests cannot turn into a query storm. - Fixed: live rows can no longer be corrupted by overlapping or cross-account
responses. Pollers are single-flight, so a slow response can't be applied out of
order and falsely mark a running request as finished; and live-view state is cleared
and invalidated on any account change — including a mid-session session expiry — so
one account's rows can never appear under another's.
Upgrade notes
- No migrations, no required config changes — a drop-in upgrade.
- If you front polyrouter with a reverse proxy, do not buffer
/api/events.
polyrouter already sendsX-Accel-Buffering: no/Cache-Control: no-transformand
heartbeats every 25s, but nginx/Traefik/Cloudflare may still need response buffering
disabled for that path (nginx:proxy_buffering off;). If the stream is blocked
nothing breaks — the dashboard shows Polling and keeps refreshing. - New optional env, all defaulted:
EVENTS_ENABLED(setfalseto disable the
stream entirely and stay on polling) andEVENTS_HEARTBEAT_MS, plus reconciliation,
per-owner-cap, queue-bound and coalesce-window knobs. Boot fails fast on an
out-of-range combination rather than silently loosening a bound. - Still one app replica only — the event stream fans out in-process; multi-instance
fanout is a documented graduation, not a supported topology.
Full package changelogs live in packages/*/CHANGELOG.md.