-
Notifications
You must be signed in to change notification settings - Fork 4
docs: add ADR for SSE bulk evaluation change notifications #63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,244 @@ | ||||||||||||||||||||||||||||||||||||||
| # 8. Server-Sent Events (SSE) for bulk evaluation changes | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Date: 2026-02-20 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## Status | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Proposed | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## Context | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| OFREP currently relies exclusively on polling for flag change detection in client-side (static context) providers. As described in [ADR-0005](0005-polling-for-bulk-evaluation-changes.md), polling was chosen initially for simplicity, with the explicit expectation that additional change detection mechanisms would be added later. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Polling has known limitations: | ||||||||||||||||||||||||||||||||||||||
| - There is no way to implement real-time flag updates | ||||||||||||||||||||||||||||||||||||||
| - Frequent polling introduces unnecessary load on flag management systems | ||||||||||||||||||||||||||||||||||||||
| - There is an inherent latency between flag changes and client awareness, bounded by the poll interval | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| The [vendor survey](https://docs.google.com/forms/d/1NzqKx57XvRK_2lRQOFCRmF5exet6f15-sCjdEy0HCS8#responses) referenced in ADR-0005 confirmed that many vendors already use SSE for change notification. Without a standardized mechanism in OFREP, each vendor must implement proprietary push solutions, undermining the protocol's goal of vendor-agnostic interoperability. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Server-Sent Events (SSE) is a W3C standard that fits this use case well: | ||||||||||||||||||||||||||||||||||||||
| - Unidirectional (server-to-client), matching the notification pattern | ||||||||||||||||||||||||||||||||||||||
| - Runs over standard HTTP without protocol upgrades | ||||||||||||||||||||||||||||||||||||||
| - Natively supported in browsers via the `EventSource` API | ||||||||||||||||||||||||||||||||||||||
| - Built-in reconnection support; when events include `id`, reconnecting clients can send `Last-Event-ID` to resume from the last processed event | ||||||||||||||||||||||||||||||||||||||
| - Works through proxies, CDNs, and standard HTTP infrastructure | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## Decision | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Add an optional `sse` array to the bulk evaluation response (`POST /ofrep/v1/evaluate/flags`). When present, it provides SSE endpoint URLs that the provider connects to for real-time flag change notifications. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| SSE is used as a **notification-only** mechanism -- events signal the provider to re-fetch the bulk evaluation via the existing endpoint, rather than streaming full evaluation payloads. This keeps the SSE message format simple, reuses existing infrastructure, and avoids duplicating evaluation logic. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Response Schema | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Add an optional `sse` field to `bulkEvaluationSuccess`: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```json | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| "flags": [ | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| "key": "discount-banner", | ||||||||||||||||||||||||||||||||||||||
| "value": true, | ||||||||||||||||||||||||||||||||||||||
| "reason": "TARGETING_MATCH", | ||||||||||||||||||||||||||||||||||||||
| "variant": "enabled" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||
| "sse": [ | ||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a big fan of this object. I prefer to not use the name of the technology here, but its purpose. "refresh": [ //I am terrible with naming so I am up for suggestions
{
"type": "sse",
"url": "http://",
"timeout": 123
}]This would allow us to add extra notification/refresh type without breaking the contract. |
||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| "url": "https://sse.example.com/event-stream?channels=env_abc123_v1", | ||||||||||||||||||||||||||||||||||||||
| "inactivityDelaySec": 120 | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||
| "metadata": { | ||||||||||||||||||||||||||||||||||||||
| "version": "v12" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Each SSE connection object has: | ||||||||||||||||||||||||||||||||||||||
| - `url` (string, required): The SSE endpoint URL. The URL is opaque to the provider and may include authentication tokens, channel identifiers, or other vendor-specific query parameters. | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
| - `url` (string, required): The SSE endpoint URL. The URL is opaque to the provider and may include authentication tokens, channel identifiers, or other vendor-specific query parameters. | |
| - `url` (string, required): The SSE endpoint URL. The URL is opaque to the provider and may include authentication tokens, channel identifiers, or other vendor-specific query parameters. Implementations MUST treat this URL as sensitive credential material and MUST NOT log or otherwise persist the full value (including query string) in application logs, analytics, error reports, or other telemetry. |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The specification states inactivityDelaySec should be used to close connections "after the specified inactivity period" (line 61), but "inactivity" is not clearly defined. Does this mean no SSE events received, no user interaction with the application, browser tab backgrounded, or device screen off? Different interpretations could lead to inconsistent behavior across implementations. Consider providing a clear definition or examples of what constitutes "inactivity" in this context.
| - `inactivityDelaySec` (integer, optional): Seconds of client inactivity (e.g., browser tab or mobile app backgrounded) after which the SSE connection should be closed. The client must reconnect and re-fetch when activity resumes. | |
| - `inactivityDelaySec` (integer, optional): Seconds since the client application last considered itself "active" for the current user/session, after which the SSE connection should be closed. Inactivity is determined by the host application (for example, a browser tab becoming hidden or suspended, a mobile app moving to the background, or a configurable period with no user interaction), and **must not** be based solely on the absence or frequency of SSE events. The client must reconnect and re-fetch when activity resumes according to its activity detection rules. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The description says etag is "Latest flag configuration validator sent over SSE metadata", but "validator" is an unclear term in this context. This should likely be "validation token" or "version identifier" to better describe ETag's purpose as a cache validation mechanism.
| - `etag` (string, optional): Latest flag configuration validator sent over SSE metadata. If present, providers should include it as the `sseEtag` query parameter on the re-fetch request. | |
| - `etag` (string, optional): Latest flag configuration validation token (version identifier) sent over SSE metadata. If present, providers should include it as the `sseEtag` query parameter on the re-fetch request. |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The specification states that lastModified in SSE events supports "either Unix timestamp in seconds (recommended) or a date string (ISO 8601 or HTTP-date)" but doesn't provide guidance on how providers should handle parsing failures or ambiguous formats. Since line 94 mentions "cross-language date parsing ambiguity", consider adding explicit error handling guidance for providers when they encounter unparseable lastModified values.
| - `lastModified` (string | integer, optional): Latest flag configuration timestamp sent over SSE metadata. Supports either Unix timestamp in seconds (recommended) or a date string (ISO 8601 or HTTP-date). If present, providers should include it as the `sseLastModified` query parameter on the re-fetch request. | |
| - `lastModified` (string | integer, optional): Latest flag configuration timestamp sent over SSE metadata. Supports either Unix timestamp in seconds (recommended) or a date string (ISO 8601 or HTTP-date). Servers **SHOULD** prefer Unix timestamps in seconds or unambiguous ISO 8601 / HTTP-date (IMF-fixdate) strings to avoid cross-language parsing ambiguity. Providers **MUST NOT** apply locale-specific or heuristic parsing, and if a `lastModified` value cannot be parsed or is otherwise ambiguous, they **MUST** treat it as absent (i.e., omit `sseLastModified` on the re-fetch) rather than guessing a value. If present and successfully parsed, providers should include it as the `sseLastModified` query parameter on the re-fetch request. |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The specification requires providers to "ignore unknown types for forward compatibility" (line 76), but doesn't specify what action providers should take when receiving an unknown event type. Should providers log it, increment a metric, or silently discard it? Consider adding guidance on how unknown event types should be handled to help with debugging and monitoring.
| - `type` (string, required): The event type. Providers must handle `refetchEvaluation` and must ignore unknown types for forward compatibility. | |
| - `etag` (string, optional): Latest flag configuration validator sent over SSE metadata. If present, providers should include it as the `sseEtag` query parameter on the re-fetch request. | |
| - `lastModified` (string | integer, optional): Latest flag configuration timestamp sent over SSE metadata. Supports either Unix timestamp in seconds (recommended) or a date string (ISO 8601 or HTTP-date). If present, providers should include it as the `sseLastModified` query parameter on the re-fetch request. | |
| - `type` (string, required): The event type. Providers must handle `refetchEvaluation` and must ignore unknown types for forward compatibility (i.e., they MUST NOT trigger a re-fetch or other functional behavior for unknown types). | |
| - `etag` (string, optional): Latest flag configuration validator sent over SSE metadata. If present, providers should include it as the `sseEtag` query parameter on the re-fetch request. | |
| - `lastModified` (string | integer, optional): Latest flag configuration timestamp sent over SSE metadata. Supports either Unix timestamp in seconds (recommended) or a date string (ISO 8601 or HTTP-date). If present, providers should include it as the `sseLastModified` query parameter on the re-fetch request. | |
| Providers MAY emit low-cost observability signals (for example, a debug-level log entry or a counter metric) when they encounter an event with an unknown `type`, but they SHOULD ensure that such signals do not cause excessive log volume or metric cardinality in the presence of high event rates. |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 86 states "Providers must perform an immediate bulk re-fetch after reconnect, even when replay is supported", but this contradicts the standard SSE reconnection pattern where Last-Event-ID is meant to resume from where the client left off. If replay is supported and working correctly, an immediate re-fetch would be redundant. Consider revising to "Providers should perform a bulk re-fetch after reconnect if replay is not supported or fails" or explaining why the redundant fetch is necessary despite replay.
| - Providers must perform an immediate bulk re-fetch after reconnect, even when replay is supported, to guarantee cache correctness across implementations with different replay retention policies. | |
| - Providers should perform an immediate bulk re-fetch after reconnect if replay is not supported, unavailable for the disconnect window, or otherwise fails, to guarantee cache correctness across implementations with different replay retention policies. |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The term "SSE-trigger metadata" is introduced on line 89 but never formally defined. Consider adding a clear definition earlier in the document explaining that this refers to metadata originating from SSE events that should be passed to the bulk evaluation endpoint when refetching, to distinguish it from standard HTTP conditional request headers.
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sequence diagram shows the server returning "200 OK (flags + sse URLs + ETag)" but the response schema example on line 38-57 doesn't show an ETag in the response body. ETags are typically HTTP headers, not body fields. Consider clarifying whether "ETag" here refers to the HTTP ETag header (from ADR-0005) or to a new body field, and update the diagram or schema example accordingly for consistency.
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sequence diagram on line 116 shows a server returning "304 Not Modified" response, but there's no specification of which headers or query parameters the server should use to determine whether the flags have changed. The document explains that sseEtag and sseLastModified are "not standard HTTP conditional request validators" (line 89), but doesn't clarify how servers should use them to decide between returning 200 vs 304. Consider adding explicit guidance on server-side validation logic.
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The specification states providers "should" send sseEtag and sseLastModified when they are present in the SSE event, but line 128 requires the provider "must re-fetch" without specifying what happens if these parameters are not included in the re-fetch. Consider clarifying whether omitting these parameters when they were present in the SSE event is a violation or just suboptimal behavior.
| 2. On receiving a `refetchEvaluation` event, the provider must re-fetch flag evaluations from the bulk evaluation endpoint. If `etag` is present, it should be sent as `sseEtag` query parameter. If `lastModified` is present, it should be sent as `sseLastModified` query parameter. These query parameters should only be included for requests directly triggered by processing that SSE event. | |
| 2. On receiving a `refetchEvaluation` event, the provider must re-fetch flag evaluations from the bulk evaluation endpoint. When the SSE event includes `etag`, the provider SHOULD send it as the `sseEtag` query parameter; when the SSE event includes `lastModified`, the provider SHOULD send it as the `sseLastModified` query parameter. These query parameters must only be included for requests directly triggered by processing that specific SSE event. Omitting `sseEtag` or `sseLastModified` when they were present in the SSE event is allowed but may reduce cache validation efficiency; providers must not fabricate or reuse values that were not present on the triggering event. |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The provider behavior guideline states providers "must" reconnect and immediately re-fetch after inactivity (line 130), but there's no specification of what should happen if this re-fetch fails. Should the provider retry, fall back to polling if configured, or emit an error event? The existing polling behavior in static-context-provider.md handles various error codes (401, 403, 429, etc.), but this ADR doesn't specify how SSE-triggered re-fetches should handle those same errors.
| 3. If `inactivityDelaySec` is specified, the provider should close the SSE connection after the specified inactivity period. On resumption, it must reconnect and immediately re-fetch without SSE query metadata. | |
| 3. If `inactivityDelaySec` is specified, the provider should close the SSE connection after the specified inactivity period. On resumption, it must reconnect and immediately re-fetch without SSE query metadata. This re-fetch is a normal bulk evaluation request and **must** follow the same error-handling, retry, and fallback semantics as other bulk evaluation or polling-triggered refresh requests (for example, handling 401/403/429/5xx according to the static-context provider guidelines) and must not enter an unbounded tight retry loop. |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 130 requires providers to "immediately re-fetch without SSE query metadata" after inactivity reconnection, but the sequence diagram on line 123 shows "POST /ofrep/v1/evaluate/flags" without any conditional headers. This is inconsistent with the existing polling behavior documented in ADR-0005 and the static-context-provider guideline, which specify that providers should send If-None-Match with the stored ETag. Consider clarifying whether the standard ETag conditional request header should still be included in this scenario.
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback behavior in line 131 states "if polling is disabled, continue SSE reconnection attempts and rely on explicit refresh triggers such as onContextChange", but this could lead to a situation where the provider has stale data indefinitely if SSE never reconnects and no context changes occur. Consider documenting this operational risk more explicitly in the Consequences section or recommending a maximum reconnection duration before requiring manual intervention.
| 4. If the SSE connection fails or is unavailable, the provider must fall back to its configured change detection behavior: if polling is enabled, continue with polling; if polling is disabled, continue SSE reconnection attempts and rely on explicit refresh triggers such as `onContextChange`. | |
| 4. If the SSE connection fails or is unavailable, the provider must fall back to its configured change detection behavior: if polling is enabled, continue with polling; if polling is disabled, continue SSE reconnection attempts and rely on explicit refresh triggers such as `onContextChange`. Implementations SHOULD also enforce a maximum reconnection duration or attempt limit and, once exceeded, surface a degraded state (for example, by emitting an error, requiring a manual refresh, or exposing health telemetry) to avoid silently serving stale data indefinitely when SSE cannot be re‑established and no other refresh triggers occur. |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 133 states "When onContextChange is triggered, the provider re-fetches the bulk evaluation without SSE query metadata. The SSE URL(s) in the new response may differ, and the provider must update its connections accordingly." However, there's no guidance on how to handle the transition period when the old SSE connection is still active but a new URL has been received. Should providers immediately close old connections and open new ones? Should they wait for a grace period? This could lead to missed events during the transition. Consider adding explicit connection lifecycle guidance for this scenario.
| 6. When `onContextChange` is triggered, the provider re-fetches the bulk evaluation without SSE query metadata. The SSE URL(s) in the new response may differ, and the provider must update its connections accordingly. | |
| 6. When `onContextChange` is triggered, the provider re-fetches the bulk evaluation without SSE query metadata. The SSE URL(s) in the new response may differ, and the provider must update its connections accordingly: | |
| - If the new response omits `sse` entirely, the provider must close any existing SSE connections and rely solely on its fallback change detection behavior. | |
| - If the new response includes `sse` and the URL set is identical to the currently connected URL(s), the provider may reuse the existing SSE connection and is not required to reconnect. | |
| - If the new response includes `sse` and the URL set differs from the currently connected URL(s), the provider SHOULD first establish connections to all new SSE URL(s), and only after successful connection attempt(s) SHOULD it close the old SSE connection(s). Providers SHOULD bound this overlap with a short grace period to avoid unbounded duplicate connections, and MUST tolerate potential duplicate notifications during the transition (for example, by treating SSE-triggered refetches as idempotent). |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SSE event data example shows "etag": "\"abc123\"" with escaped quotes (line 72), but the query parameter example shows "\"550e8400-e29b-41d4-a716-446655440000\"" also with escaped quotes (line 149). This double-quoting convention (ETags typically include literal quote characters per RFC 7232) should be explicitly documented to avoid implementation confusion, as providers will need to handle the quote escaping when constructing the query parameter.
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent terminology: Line 78 uses "Unix timestamp in seconds" but line 155 uses "Unix timestamp seconds" (without "in"). For consistency throughout the document, use the same phrasing in both locations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The oneOf schema for sseLastModified correctly specifies integer and string types. However, the examples section only provides epochSeconds for the integer type. It would be clearer to explicitly show examples for both isoDate and httpDate under the string type to fully illustrate the supported formats.
| oneOf: | |
| - type: integer | |
| minimum: 0 | |
| - type: string | |
| required: false | |
| schema: | |
| oneOf: | |
| - type: integer | |
| minimum: 0 | |
| - type: string | |
| required: false | |
| examples: | |
| epochSeconds: | |
| value: 1771622898 | |
| isoDate: | |
| value: "2026-02-20T21:28:18Z" | |
| httpDate: | |
| value: "Thu, 20 Feb 2026 21:28:18 GMT" |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The OpenAPI schema addition specifies inactivityDelaySec with minimum: 0 (line 203) and states "If omitted or 0, the connection should be maintained indefinitely" (line 207-208). However, having a minimum of 0 means 0 is a valid value, which creates ambiguity - does 0 mean "close immediately" or "maintain indefinitely"? Consider either removing 0 from the valid range (use minimum: 1) or clarifying the semantics more explicitly.
| minimum: 0 | |
| description: | | |
| Number of seconds of client inactivity after which the SSE connection | |
| should be closed to conserve resources. The client must reconnect | |
| when activity resumes. If omitted or 0, the connection should be | |
| minimum: 1 | |
| description: | | |
| Number of seconds of client inactivity after which the SSE connection | |
| should be closed to conserve resources. The client must reconnect | |
| when activity resumes. If omitted, the connection should be |
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 227 mentions "re-fetch amplification risk" when multiple SSE URLs trigger redundant concurrent re-fetches, but the provider behavior guidelines don't specify any required coalescing behavior. While Open Question 3 asks about coalescing strategy, the lack of any mandatory coalescing in the main specification could lead to implementations that amplify load significantly. Consider adding at least a basic requirement like "providers SHOULD debounce re-fetch requests within a configurable time window" to the provider behavior section.
| - **Re-fetch amplification risk**: Multiple SSE URLs or bursty event streams can trigger redundant concurrent re-fetches unless providers coalesce events | |
| - **Re-fetch amplification risk**: Multiple SSE URLs or bursty event streams can trigger redundant concurrent re-fetches unless providers coalesce events. To mitigate this, providers MUST avoid issuing redundant concurrent re-fetches for the same bulk evaluation request (for example, via in-flight de-duplication) and SHOULD debounce re-fetch requests within a configurable time window. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the developer be able to opt out of SSE via a config option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well SSE is totally optional, it basically comes down to if the Server responds with an sse object or not. But yes the Providers should also have a disable SSE option in them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest allowing the developer to choose as a setting:
- none
- pooling
- sse
This would give more control to the developer to pick up their preferred way for refreshing the flags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe as a potential v2 for SSE, I would like to experiment having a json PATCH similar behaviour. What I mean is, instead of forcing a full refresh, the event would send the flags that need to be updated.
For example:
[
{ "op": "add", flagKey: "test", value: { } },
{ "op": "replace", flagKey: "test", "path": "/defaultValue", "value": "false" },
{ "op": "remove", flagKey: "test"}
]
This adds extra complexity but it would be a good improvement.
Copilot
AI
Feb 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open Question 6 asks "Should SSE metadata be transported via query parameters or custom headers?" and notes the recommendation is query params. However, the justification in lines 91-92 mentions "query parameters avoid CORS preflight costs that would be introduced by custom headers" - but this only applies to browser environments. For non-browser SDKs (server-side, mobile native apps), custom headers would be more conventional. Consider revising the specification to allow either approach, with query params recommended for browsers and custom headers as an alternative for non-browser environments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would consider adding that mobile is also supported. After a quick search I confirmed that.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea Mobile should be supported with SSE will make that clearer. I recommend that we stick to the LaunchDarkly Event Source libraries where its not built-in: