Skip to main content
The SDK opens a persistent GET /v1/stream connection after the initial sync completes. Whenever the Nexus backend emits a change event (config.updated, flag.toggled, secret.created, resync, …), the SDK triggers an immediate full re-sync - so the in-memory cache is updated within milliseconds of a change, instead of waiting for the next TTL tick.

Auth

Node.js uses the X-Nexus-API-Key header on all endpoints, including /stream, via the native http/https modules. The key is never passed as a ?key= query parameter. (All Nexus SDKs send the key in this header - the browser SDKs do too, using fetch-based streaming rather than the EventSource API.)

What happens under the hood

  1. The SDK opens an HTTP streaming response to <endpoint>/v1/stream with Accept: text/event-stream and the X-Nexus-API-Key header.
  2. The server immediately sends a resync event, which causes the SDK to call _sync() once to align with the current state.
  3. The connection stays open. Every change event triggers another full sync.
  4. While the stream is up, the polling interval is bumped to 60 s as a safety net.

Reconnection

Any transport error (server restart, TCP drop, network blip) triggers a reconnect with exponential backoff: 1s - 2s - 4s - 8s - 16s - 30s (capped at 30s). After three consecutive transport errors the SDK closes the stream and enters a reconnect cooldown. Reads continue to be served from the cache (propagation latency increases to the polling TTL), but the stream is not abandoned permanently. The SDK sleeps for the next interval in the sseReconnectCooldown schedule (default: 5 min, then 10, 20, 40, 60 min, staying at 60 min thereafter) and then automatically reopens /v1/stream.
The reconnect schedule is controlled by the sseReconnectCooldown config field (unit: minutes). The default schedule [5, 10, 20, 40, 60] means the first retry happens after 5 minutes, the second after 10, and so on - capping at 60 minutes for all subsequent attempts. Pass a single number for a fixed interval, or a custom array for a different progression. See Configuration for the full field reference.

429 Too Many Requests

Every project tier has a per-service stream connection limit: Exceeding the limit returns 429 Too Many Requests. Behaviour depends on whether the response carries a parseable Retry-After header.

Behaviour (v0.6.0+)

Quarantine 429 ({"error":"quarantined","reason":"...","expires_at":"..."} body):
  1. The SDK reads the response body and detects the quarantine payload.
  2. It fires observer.onQuarantined(reason, expiresAt) - NOT onFallback.
  3. It schedules an automatic reconnect at expiresAt (minimum 5 s). This path does not count toward MAX_FAILURES.
  4. When the timer fires, the SDK reopens /v1/stream normally.
Rate-limit 429 with a parseable Retry-After header (delta-seconds, e.g. Retry-After: 30):
  1. The SDK parses the header and clamps the delay to the range [5 s, 5 min].
  2. It fires observer.onFallback(FALLBACK_REASON_RATE_LIMITED) so dashboards and load-test tooling can record the episode.
  3. It schedules a single setTimeout-based reconnect after the clamped delay. This path does not touch backoffMs or failedAttempts - Retry-After is cooperative back-pressure, not a transport error, so it does NOT count toward MAX_FAILURES.
  4. When the timer fires, the SDK reopens /v1/stream normally.
Without a parseable Retry-After header:
  1. The SDK fires observer.onFallback(FALLBACK_REASON_RATE_LIMITED).
  2. client.streamStatus becomes 'fallback' and the stream is closed.
  3. The SDK schedules a reconnect using the sseReconnectCooldown schedule (default: 5 min → 10 → 20 → 40 → 60 min). When the timer fires, the SDK reopens /v1/stream normally.

Disabling SSE

Useful if you want to react to a “go offline” / “reduce traffic” signal without disposing the whole client. Reconnect later with client.connectStream().

What events trigger a sync

Lifecycle

The stream is bound to the NexusClient instance. client.close() cancels the connection along with the polling timer and the temp-file cleanup. Always call close() on shutdown:

Inspecting status