Real-Time Updates
How SSE delivers instant flag changes
Flipswitch uses Server-Sent Events (SSE) to push flag changes to connected clients instantly.
How It Works
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Dashboard │ │ Flipswitch │ │ Your App │
│ │ │ Server │ │ (SDK) │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
│ Toggle flag "dark-mode" │
│──────────────────────>│ │
│ │ │
│ │ SSE: flag-updated │
│ │──────────────────────>│
│ │ │
│ │ Invalidate cache │
│ │ │
│ │ Next evaluation │
│ │<──────────────────────│
│ │ │
│ │ Fresh flag value │
│ │──────────────────────>│
│ │ │- You toggle a flag in the dashboard
- Server broadcasts a
flag-updatedevent to all connected SDKs - SDKs invalidate their local cache
- Next flag evaluation fetches the fresh value
The result: flag changes propagate in milliseconds, not minutes.
Why SSE?
Instant updates. Polling can take 30-60 seconds to detect changes. SSE delivers them immediately.
Kill switches that work. When something breaks, you need to disable features now, not "whenever the next poll happens."
Lower server load. One long-lived connection per client vs. constant polling requests.
Simple protocol. SSE is HTTP with a text/event-stream content type. Works through proxies, load balancers, and firewalls that understand HTTP.
Event Types
Flipswitch emits two types of SSE events:
flag-updated
Sent when a single flag is created, updated, or deleted.
event: flag-updated
data: {"flagKey":"dark-mode","timestamp":"2024-01-21T10:30:45.123Z"}
id: 1705844445123| Field | Description |
|---|---|
flagKey | The key of the flag that changed |
timestamp | When the change occurred (ISO 8601) |
SDK behavior: Invalidate the specific flag from cache, then re-evaluate on next access.
config-updated
Sent when configuration changed that may affect multiple flags. Clients should re-evaluate all flags.
event: config-updated
data: {"reason":"segment-modified","timestamp":"2024-01-21T10:30:45.123Z"}
id: 1705844445123| Field | Description |
|---|---|
reason | Why the configuration update occurred |
timestamp | When the change occurred (ISO 8601) |
Possible reasons:
segment-modified— A segment rule was created, updated, or deletedapi-key-rotated— API key was regenerated
SDK behavior: Invalidate the entire cache, then re-fetch all flags on next evaluation.
heartbeat
Sent every 15 seconds to keep the connection alive.
event: heartbeat
data: {}No action required from clients. This event helps detect stale connections and prevents proxy timeouts.
SDK Behavior
All official SDKs support SSE by default:
// SSE enabled by default
const provider = new FlipswitchWebProvider({
apiKey: 'YOUR_API_KEY',
enableRealtime: true // default
});// SSE enabled by default
const provider = new FlipswitchServerProvider({
apiKey: 'YOUR_API_KEY',
enableRealtime: true // default
});// SSE enabled by default
FlipswitchProvider provider = FlipswitchProvider.builder("YOUR_API_KEY")
.enableRealtime(true) // default
.build();# SSE enabled by default
provider = FlipswitchProvider(
api_key="YOUR_API_KEY",
enable_realtime=True # default
)// SSE enabled by default
provider, _ := flipswitch.NewProvider(
"YOUR_API_KEY",
flipswitch.WithRealtime(true), // default
)When the SSE connection receives a flag event (flag-updated or config-updated):
- The local cache is invalidated
- OpenFeature emits a
PROVIDER_CONFIGURATION_CHANGEDevent - If using React,
useFlaghooks re-render automatically
Connection Status
SDKs track connection state:
const status = provider.getSseStatus();
// 'connecting' | 'connected' | 'disconnected' | 'error'SseClient.ConnectionStatus status = provider.getSseStatus();
// CONNECTING, CONNECTED, DISCONNECTED, ERRORstatus = provider.get_sse_status()
# ConnectionStatus.CONNECTING, CONNECTED, DISCONNECTED, ERRORstatus := provider.GetSseStatus()
// flipswitch.StatusConnecting, StatusConnected, StatusDisconnected, StatusError| Status | Meaning |
|---|---|
connecting | Establishing SSE connection |
connected | Receiving events |
disconnected | Connection lost, will retry |
error | Connection failed |
Reconnection
SDKs automatically reconnect with exponential backoff:
- Initial delay: 1 second
- Maximum delay: 30 seconds
- Backoff multiplier: 2x
While disconnected, the SDK continues working with cached values. When reconnected, it fetches fresh data.
Disabling SSE
If you don't need real-time updates:
const provider = new FlipswitchWebProvider({
apiKey: 'YOUR_API_KEY',
enableRealtime: false,
pollingInterval: 60000 // Poll every 60 seconds instead
});const provider = new FlipswitchServerProvider({
apiKey: 'YOUR_API_KEY',
enableRealtime: false,
pollingInterval: 60000 // Poll every 60 seconds instead
});FlipswitchProvider provider = FlipswitchProvider.builder("YOUR_API_KEY")
.enableRealtime(false)
.cacheTtl(Duration.ofSeconds(60)) // Poll every 60 seconds instead
.build();provider = FlipswitchProvider(
api_key="YOUR_API_KEY",
enable_realtime=False,
# SDK will fall back to polling
)provider, _ := flipswitch.NewProvider(
"YOUR_API_KEY",
flipswitch.WithRealtime(false),
// SDK will fall back to polling
)Without SSE, flag changes only appear after the polling interval. Kill switches won't be instant.
Proxy Considerations
SSE requires long-lived HTTP connections. Some proxies and load balancers may close connections after a timeout.
If you see frequent disconnections:
- Configure your proxy to allow longer connection timeouts
- Check for intermediate proxies (CDNs, API gateways) that may buffer responses
- Ensure
Transfer-Encoding: chunkedis supported