Skip to main content
The SDK can hold a persistent GET /v1/stream connection open in the background. Whenever the Nexus backend emits a change event (config.updated, flag.toggled, secret.created, resync, …), the SDK triggers an immediate full sync - so the cache is updated within milliseconds of the change, instead of waiting for the next TTL tick. Both NexusClient and AsyncNexusClient support SSE; they just use different concurrency primitives (a daemon thread vs an asyncio.Task).

Auth

Python uses the X-Nexus-API-Key header on all endpoints, including /stream, via httpx’s streaming support. 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.)

Enabling it

The stream starts automatically after the initial sync (stream=True is the default in NexusConfig).
To run in pure TTL-polling mode:

What happens under the hood

  1. The SDK opens an HTTP streaming response via httpx.Client.stream("GET", ...) (or AsyncClient.stream for async) 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 TTL 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 does not fall back permanently. Instead it sleeps the sse_reconnect_cooldown schedule (default 5 - 10 - 20 - 40 - 60 minutes, staying at 60 minutes thereafter) and then retries the SSE connection automatically. Your application is never notified, and stream_connected stays False during the cooldown period.
The reconnect schedule is configurable via sse_reconnect_cooldown in NexusConfig. See Configuration for details.

429 Too Many Requests

Every project tier has a per-service stream connection limit:

Behaviour (v0.6.0+)

The Python SDK handles 429 with presence-conditional refinement of Retry-After:
  • With a parseable Retry-After: the SDK parses the delta-seconds value, clamps it to [5, 300] seconds, fires observer.on_fallback(FALLBACK_REASON_RATE_LIMITED), sleeps the indicated delay on the stream’s stop event, and then resumes the reconnect loop. The 429 does not count toward _MAX_STREAM_ERRORS.
  • Without a parseable Retry-After: the SDK fires observer.on_fallback(FALLBACK_REASON_RATE_LIMITED) and schedules a reconnect using the sse_reconnect_cooldown schedule (default 5 - 10 - 20 - 40 - 60 minutes). TTL polling covers the gap during the cooldown, and the stream retries automatically.
Both clients implement the same logic using their respective sleep primitives:
  • AsyncNexusClient - await asyncio.wait_for(self._stream_stop.wait(), timeout=retry_after), so an in-flight close() / disconnect_stream() wakes the sleeping task immediately.
  • NexusClient (sync) - self._stream_stop.wait(timeout=retry_after) on a threading.Event, with the same prompt-shutdown property.

Disabling SSE at runtime

Reconnect later with connect_stream() (sync) or nexus.connect_stream() (async).

What events trigger a sync

Lifecycle

The SSE thread (sync) or task (async) is bound to the client. Calling close() stops it cleanly along with the rest of the client teardown. Always call close() on shutdown:

Inspecting status