Automatic connection
SSE streaming is exclusive to the server entry point — it is never available from the browser entry. Import CanaryGate from @canarygate/sdk/js/server to enable it; @canarygate/sdk/js/client always uses the snapshot request only.
init() always starts with a snapshot request that loads the current flags. Real-time updates depend on the entry point:
- Browser (
@canarygate/sdk/js/client): streaming is disabled by design. Flags are loaded via a single HTTP snapshot request (/sdk/flags), andstream: trueis ignored (a warning is logged). This prevents thousands of open SSE connections coming from browsers. - Server (
@canarygate/sdk/js/server, for Node.js, Deno, Bun, Edge): passstream: trueto open an SSE connection after the snapshot. Flags are then updated in the background without polling.
// Server, real-time: snapshot + SSE stream
import { CanaryGate } from '@canarygate/sdk/js/server'
const realtimeClient = new CanaryGate('cg_key', { stream: true })
await realtimeClient.init()
// From this point on, realtimeClient.getFlag() always returns
// the latest value without needing a manual refetchReacting 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/js/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
}In browsers real-time SSE is disabled, so the polling approach above is the
recommended way to pick up flag changes. On the server, prefer stream: true.
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.