GET /v1/stream and refreshes the cache
whenever the server says something changed, so a flag toggled in the admin
console reaches the browser in milliseconds rather than at the next TTL tick.
The connection is a fetch stream, and the key travels in the
X-Nexus-API-Key header - never in the URL, where it would land in server access
logs and browser history.
Lifecycle
Two deadlines
Connect.streamConnectTimeoutMs (15 s) bounds the attempt to open the
stream. Only the attempt: an open stream has no total deadline, because it is
meant to last as long as the page does.
Liveness. streamIdleTimeoutMs (90 s) is the deadline that matters once the
stream is open. Every received byte resets it - keepalive comments included - so
a healthy but quiet stream stays open indefinitely, while a connection dropped
silently by a proxy or a load balancer is detected instead of reading as healthy
forever.
When it fails
Each failure schedules a reconnect on an exponential schedule with jitter: roughly 1 s, then 2 s, then 4 s. After three consecutive failures the SDK stops trying, emits themax-errors fallback, and relies on TTL polling; the
stream is retried on the cooldown schedule.
The jitter matters at scale. Without it, every tab of every browser holding a
client reconnects on exactly the same schedule after a shared outage, turning
recovery into a synchronised burst against the server that has just come back.
When it never connects at all
A stream that fails from the start is a different problem from one that drops: the values are correct on the first read and then never change, which looks like a working integration with a quiet configuration. Because the SDK has no logger by default, this used to leave no trace anywhere. The client now says so once, after it gives up on its first connection:console.warn if you configured none - so the message reaches the consumer least likely to be looking for it. A connection lost after one succeeded is not reported this way; that is what useNexusStreamStatus() and the stream observer are for.
The usual causes in a browser are CORS-shaped. The stream request carries X-Nexus-API-Key, which is not a CORS-safelisted header, so the browser preflights it: the endpoint has to allow this origin and name that header in Access-Control-Allow-Headers. A blocked preflight is indistinguishable from an unreachable server to the SDK, which is why the message names both.
Rate limits and quarantine
A429 carrying Retry-After is honoured, clamped to 5-300 seconds. A 429
without one goes straight to the cooldown schedule. A quarantine response
suspends both syncing and the stream until it expires, and is reported through
onQuarantined - it is the server telling the client exactly how long to stay
away, so it does not count as a transport failure.
Server-side rendering
The stream is never opened on the server, and neither is the freshening timer: a single render pass has nothing to re-evaluate. A long-lived connection there would have no teardown hook and would hold the response open, one leaked connection per rendered request. The stream opens in the browser, after hydration.app.unmount() is never called on a server-rendered application, so close the
client yourself on that path - the one provideNexus() returns.
