Push flag changes instantly via SSE or gRPC streaming — connection lifecycle, reconnection, and scaling
Real-Time Updates
Flaggr supports two real-time update mechanisms for pushing flag changes to connected clients without polling.
SSE (Server-Sent Events)
The default real-time protocol for browser clients. Uses the standard EventSource API.
Connect Stream (Recommended)
GET /api/connect/stream?serviceId=web-app&environment=production&clientId=client-1
Each client should provide a unique clientId for connection tracking and deduplication.
Query parameters:
| Parameter | Required | Description |
|---|---|---|
serviceId | Yes | Service to subscribe to |
environment | Yes | development, staging, or production |
clientId | Yes | Unique client identifier |
flagKey | No | Subscribe to specific flags (repeatable) |
Event Format
Events arrive as JSON payloads:
{
"eventType": "UPDATED",
"flagKey": "checkout-v2",
"flag": {
"key": "checkout-v2",
"enabled": true,
"defaultValue": true
},
"timestamp": "2025-07-20T10:30:00Z",
"configVersion": "v42"
}Event types:
| Type | Description |
|---|---|
PROVIDER_READY | Initial connection established, current config sent |
CREATED | New flag created |
UPDATED | Existing flag configuration changed |
DELETED | Flag removed |
SYNC | Full configuration sync |
HEARTBEAT | Keep-alive (every 30 seconds) |
Browser Usage
const eventSource = new EventSource(
'/api/connect/stream?serviceId=web-app&environment=production&clientId=browser-1'
)
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data)
if (data.eventType === 'UPDATED') {
console.log(`Flag ${data.flagKey} changed`)
// Update local flag cache
}
}
eventSource.onerror = () => {
console.log('Connection lost, EventSource will auto-reconnect')
}The browser's EventSource API automatically reconnects on connection loss with exponential backoff. You don't need to implement reconnection logic.
SDK Integration
The web provider handles SSE internally:
const provider = new FlaggrWebProvider({
apiUrl: 'https://flaggr.dev',
serviceId: 'web-app',
enableStreaming: true, // Enables SSE
})
// Flag changes are applied automatically
// Hook consumers re-render when values changegRPC Streaming
Server-side streaming for high-throughput environments. Provides bidirectional communication with lower overhead than SSE.
Connection Setup
import { GrpcProvider } from '@flaggr/client'
const provider = new GrpcProvider({
grpcAddress: 'flaggr.dev:50051',
serviceId: 'payment-service',
environment: 'production',
apiToken: 'flg_your_token',
flagKeys: ['checkout-v2', 'dark-mode'], // Subscribe to specific flags
})Streaming Lifecycle
Client Server
│ │
├── StreamFlags(request) ──────►│
│ │
│◄── PROVIDER_READY (full config)│
│ │
│ ... time passes ... │
│ │
│◄── UPDATED (flag changed) ───│
│◄── CREATED (new flag) ───────│
│ │
│ ... heartbeat ... │
│◄── HEARTBEAT ────────────────│
│ │
Reconnection
The gRPC provider includes automatic reconnection with configurable backoff:
const provider = new GrpcProvider({
grpcAddress: 'flaggr.dev:50051',
serviceId: 'my-service',
reconnect: {
enabled: true,
maxAttempts: 10,
initialDelayMs: 1000, // Start at 1s
maxDelayMs: 30000, // Cap at 30s
},
})Delivery Architecture
Primary: Redis Pub/Sub
When Redis is configured, flag changes are published to a Redis channel. All SSE and gRPC stream handlers subscribe to this channel for instant delivery.
Flag Update → Redis PUBLISH → All Stream Handlers → Connected Clients
Fallback: Polling
When Redis is unavailable, the stream handlers fall back to polling the database every 5 seconds. This is transparent to clients.
Without Redis, in-memory broadcast only reaches clients connected to the same instance. For multi-instance deployments, Redis is required for cross-instance flag change delivery.
Protocol Comparison
| Feature | SSE | gRPC Streaming |
|---|---|---|
| Browser support | Native | Via gRPC-Web |
| Server support | No | Yes |
| Bidirectional | No | Yes |
| Auto-reconnect | Browser-native | Custom logic |
| Overhead | HTTP/1.1 | HTTP/2 binary |
| Connection limit | 6 per domain | Unlimited |
| Best for | SPAs, dashboards | Microservices |
Connection Monitoring
Track connection state in your application:
provider.onConnectionStateChange((state) => {
// CONNECTING → CONNECTED → DISCONNECTED → ERROR
console.log('Connection state:', state)
if (state === 'ERROR') {
// Show fallback UI or use cached values
}
})The useConnectionState() React hook provides this in components:
function StatusBadge() {
const state = useConnectionState()
return state === 'CONNECTED'
? <span className="text-green-500">Live</span>
: <span className="text-yellow-500">Reconnecting...</span>
}Metrics
Real-time connections are tracked via Prometheus:
| Metric | Description |
|---|---|
flaggr_grpc_active_connections | Active gRPC streaming connections |
flaggr_grpc_active_streams | Active gRPC streams |
flaggr_grpc_messages_total | Total gRPC messages (by direction) |
SSE connections are tracked as active connections with an endpoint label (connect or legacy).
Related
- Protocols — Protocol comparison and setup
- Provider Architecture — Web and gRPC provider details
- Caching Strategy — How caching interacts with real-time updates