Skip to Content
SDKJavaScript / TypeScriptReal-time SSE

Automatic connection

SSE is exclusive to the server entry point and is always on — there is no option to enable or disable it. The browser entry never uses SSE; it receives updates via native polling (pollIntervalMs).

init() always starts with a snapshot request that loads the current flags. Real-time updates depend on the entry point:

  • Browser (@canarygate/sdk/client): never uses SSE. Flags are loaded via a snapshot request (/sdk/flags) and refreshed automatically by polling every pollIntervalMs (default 30000, clamped to a 3000ms minimum, 0 disables). This prevents thousands of open SSE connections coming from browsers.
  • Server (@canarygate/sdk/server, for Node.js, Deno, Bun, Edge): always opens an SSE connection after the snapshot. Flags are then updated in the background without polling.
// Server, real-time: snapshot + SSE stream (always on) import { CanaryGate } from '@canarygate/sdk/server' const realtimeClient = new CanaryGate('cg_key') await realtimeClient.init() // From this point on, realtimeClient.getFlag() always returns // the latest value without needing a manual refetch

If the server entry is used where a window exists (browser), the constructor throws; import from @canarygate/sdk/client instead. Likewise, the client entry throws if used in an environment without window.

Reacting to changes (React)

For React components to reflect real-time flag changes, you need a reactivity mechanism. The SDK does not include native React bindings, but it is straightforward to implement:

import { CanaryGate } from '@canarygate/sdk/client' import { useState, useEffect, useRef } from 'react' function useFlagEnabled(client: CanaryGate, key: string): boolean { const [enabled, setEnabled] = useState( () => client.getFlag(key)?.enabled ?? false ) useEffect(() => { const interval = setInterval(() => { const current = client.getFlag(key)?.enabled ?? false setEnabled(current) }, 500) return () => clearInterval(interval) }, [client, key]) return enabled }

On the server the SSE stream is always on; in browsers prefer the SDK’s built-in polling (pollIntervalMs). Since the SDK already polls internally, the setInterval in the example above is not strictly necessary — but it is safe to keep.

isStale()

Returns true when the last flags sync failed or the stream connection is down (for example, while reconnecting). Use it to detect a degraded state.

if (client.isStale()) { // Data may be stale // Consider reloading or showing a warning to the user }

Use isStale() to monitor connection health in critical dashboards.

getLastSyncAt()

Returns the ISO timestamp (string | null) of the last successful sync, or null if init() has not completed yet.

const lastSync = client.getLastSyncAt() if (lastSync) { console.log('Flags updated', Date.now() - new Date(lastSync).getTime(), 'ms ago') }

disconnect()

Closes the stream connection (if any) and releases resources. Always call this on teardown:

// React: useEffect(() => { return () => client.disconnect() }, []) // Node.js / script: process.on('SIGTERM', () => client.disconnect())

After disconnect(), getFlag() continues to return the last known values, but will no longer receive updates.

Last updated on