From 676bb1ccbef52e9c649768b4dde114c7802fcd6b Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Tue, 27 Oct 2026 14:25:35 +0000 Subject: [PATCH 01/12] Document flag selection for the browser SDK Add a Load a subset of flags section to the JavaScript client page and a proxy note for the DD-Flag-Selection-Ignored header. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- .../en/feature_flags/client/javascript.md | 77 +++++++++++++++++++ .../feature_flags/guide/proxy_sdk_traffic.md | 3 + 2 files changed, 80 insertions(+) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index e6c2f26c1b65..24498454a240 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -245,6 +245,82 @@ The web provider also supports these optional settings: | `customHeaders` | unset | Add headers to flag-fetch requests. | | `overwriteRequestHeaders` | `false` | Replace default request headers with `customHeaders`. | | `flagConfigurationFetch` | `globalThis.fetch` | Provide a Fetch-compatible implementation for flag configuration requests. | +| `flagSelection` | unset | Load only the flags that match a set of tags or key patterns. See [Load a subset of flags](#load-a-subset-of-flags). | + +### Load a subset of flags + + +In `@datadog/openfeature-browser` X.Y.Z and later, use `flagSelection` to load only the flags your application needs instead of every flag in the environment. Selecting a subset reduces the size of the flag configuration the SDK downloads and caches, which helps when an environment contains flags for many applications. + +`flagSelection` accepts two optional lists: + +`tags` +: Flag tags to match, such as `app:checkout-web`. A flag matches if it has any of the listed tags. Tags match exactly and are case-sensitive. + +`keyPatterns` +: Patterns to match against the whole flag key. `*` matches any sequence of characters, including none, anywhere in the pattern. Every other character, including `?`, `[`, `]`, `{`, and `}`, matches only itself. For example, `checkout-*` matches `checkout-banner` but not `new-checkout-banner`, and `*-checkout-*` matches `new-checkout-banner`. + +A flag loads if it matches any listed tag **or** any key pattern. In the following example, the SDK loads every flag tagged `app:checkout-web` and every flag whose key starts with `checkout-`: + +```javascript +import { DatadogProvider } from '@datadog/openfeature-browser'; + +const provider = new DatadogProvider({ + applicationId: '', + clientToken: '', + site: '{{< region-param key="dd_site" code="true" >}}', + env: '', + flagSelection: { + tags: ['app:checkout-web'], + keyPatterns: ['checkout-*'], + }, +}); +``` + +The selection is fixed when you create the provider. To load a different set of flags, create a new provider. + +
Add tags to your flags specifically for selection, such as app:checkout-web, rather than selecting by team tags. A flag's team tags can change when ownership changes, which would change the flags your application loads.
+ +#### Limits and validation + +Before sending the selection, the SDK trims leading and trailing whitespace from each value, removes empty values and duplicates, and sorts each list. After this processing, the selection must meet these limits: + +- Each list (`tags` and `keyPatterns`) contains at most 31 values. +- Each tag and each key pattern is at most 200 bytes when encoded as UTF-8. + +If the selection is malformed or exceeds a limit, the SDK does not send it, logs an error to the browser console, and loads the full flag configuration. + +Datadog can also ignore a selection and return the full flag configuration. In that case, the response includes a `DD-Flag-Selection-Ignored` header with one of the following reasons, and the SDK logs an error to the browser console: + +| Reason | Meaning | +| --- | --- | +| `too_many_values` | A list contains more than 31 values. | +| `invalid_tag` | A tag is longer than 200 bytes. | +| `invalid_key_pattern` | A key pattern is longer than 200 bytes. | +| `malformed_selection` | The selection could not be parsed. | +| `tag_load_failed` | Flag tags could not be loaded for this request. The full configuration is returned so that evaluation can continue. | + +If you route flag configuration requests through a proxy, see [Proxy Feature Flag SDK Traffic][7] for the header your proxy must pass through. + +#### Evaluate flags outside the selection + +When Datadog applies the selection, flags outside it are not loaded. Evaluating one of these flags returns the default value you supply, with the error code `FLAG_NOT_FOUND`: + +{{< code-block lang="javascript" >}} +// 'search-ranking' has no app:checkout-web tag and does not match checkout-* +const details = client.getBooleanDetails('search-ranking', false); + +console.log(details.value); // false (the supplied default) +console.log(details.errorCode); // 'FLAG_NOT_FOUND' +{{< /code-block >}} + +#### Initial configuration is not filtered + +`flagSelection` applies only to configuration that the SDK fetches. The SDK does not filter configuration you supply with `initialFlagsConfiguration`, so flags in that configuration remain available even if they are outside the selection. + +#### Rules-based configuration + +`fetchRulesConfiguration()` from `@datadog/openfeature-browser/rules-based` accepts the same `flagSelection` option, with the same matching rules and limits. If the selection would make the request URL too long, the SDK does not send it and loads the full configuration. See [Browser Rules-Based Evaluation][4]. ### Supply initial precomputed fallback data @@ -368,3 +444,4 @@ The Web SDK flag shape requires `variants`, `defaultVariant`, and `disabled`. Om [4]: /feature_flags/implementation_patterns/browser_rules_based_evaluation/ [5]: /feature_flags/concepts/monthly_flag_configuration_requests/ [6]: /feature_flags/implementation_patterns/browser_rules_based_evaluation/#getting-started +[7]: /feature_flags/guide/proxy_sdk_traffic/ diff --git a/hugo/content/en/feature_flags/guide/proxy_sdk_traffic.md b/hugo/content/en/feature_flags/guide/proxy_sdk_traffic.md index b99eb1abb172..21941be06c10 100644 --- a/hugo/content/en/feature_flags/guide/proxy_sdk_traffic.md +++ b/hugo/content/en/feature_flags/guide/proxy_sdk_traffic.md @@ -203,6 +203,8 @@ DatadogBrowserFlagging.init({ }); {{< /code-block >}} +If you use [`flagSelection`][3] to load a subset of flags, return the `DD-Flag-Selection-Ignored` response header to the browser unchanged, and include it in the `Access-Control-Expose-Headers` response header. Datadog sets this header when it ignores a selection and returns the full flag configuration. If the browser cannot read the header, the full configuration still loads, but the SDK cannot report that the selection was ignored. + ### Event upload proxy Browser flag event data (exposures and evaluations) is sent through the standard Browser SDK intake pipeline. To route this traffic through a proxy, set the `proxy` option to a URL on your domain. @@ -234,6 +236,7 @@ The `proxy` option also accepts a function that receives the decoded `path` and [1]: /getting_started/site/ [2]: /real_user_monitoring/guide/proxy-rum-data/ +[3]: /feature_flags/client/javascript/#load-a-subset-of-flags {{% /tab %}} From 0c7eb45d70e07bfc3389fd9f58d5b787ea1877e3 Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Tue, 27 Oct 2026 16:16:16 +0000 Subject: [PATCH 02/12] Move flag selection under Initialize the provider Nest the Load a subset of flags section under Initialize the provider, since flagSelection is set when the provider is created. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- .../en/feature_flags/client/javascript.md | 148 +++++++++--------- 1 file changed, 73 insertions(+), 75 deletions(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 24498454a240..ec7b2f3ca78b 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -85,6 +85,79 @@ const provider = new DatadogProvider({ }); ``` +### Load a subset of flags + + +In `@datadog/openfeature-browser` X.Y.Z and later, use `flagSelection` to load only the flags your application needs instead of every flag in the environment. Selecting a subset reduces the size of the flag configuration the SDK downloads and caches, which helps when an environment contains flags for many applications. Pass `flagSelection` to the provider when you create it; the selection is fixed for the provider's lifetime, so to load a different set of flags, create a new provider. + +`flagSelection` accepts two optional lists: + +`tags` +: Flag tags to match, such as `app:checkout-web`. A flag matches if it has any of the listed tags. Tags match exactly and are case-sensitive. + +`keyPatterns` +: Patterns to match against the whole flag key. `*` matches any sequence of characters, including none, anywhere in the pattern. Every other character, including `?`, `[`, `]`, `{`, and `}`, matches only itself. For example, `checkout-*` matches `checkout-banner` but not `new-checkout-banner`, and `*-checkout-*` matches `new-checkout-banner`. + +A flag loads if it matches any listed tag **or** any key pattern. In the following example, the SDK loads every flag tagged `app:checkout-web` and every flag whose key starts with `checkout-`: + +```javascript +import { DatadogProvider } from '@datadog/openfeature-browser'; + +const provider = new DatadogProvider({ + applicationId: '', + clientToken: '', + site: '{{< region-param key="dd_site" code="true" >}}', + env: '', + flagSelection: { + tags: ['app:checkout-web'], + keyPatterns: ['checkout-*'], + }, +}); +``` + +
Add tags to your flags specifically for selection, such as app:checkout-web, rather than selecting by team tags. A flag's team tags can change when ownership changes, which would change the flags your application loads.
+ +#### Limits and validation + +Before sending the selection, the SDK trims leading and trailing whitespace from each value, removes empty values and duplicates, and sorts each list. After this processing, the selection must meet these limits: + +- Each list (`tags` and `keyPatterns`) contains at most 31 values. +- Each tag and each key pattern is at most 200 bytes when encoded as UTF-8. + +If the selection is malformed or exceeds a limit, the SDK does not send it, logs an error to the browser console, and loads the full flag configuration. + +Datadog can also ignore a selection and return the full flag configuration. In that case, the response includes a `DD-Flag-Selection-Ignored` header with one of the following reasons, and the SDK logs an error to the browser console: + +| Reason | Meaning | +| --- | --- | +| `too_many_values` | A list contains more than 31 values. | +| `invalid_tag` | A tag is longer than 200 bytes. | +| `invalid_key_pattern` | A key pattern is longer than 200 bytes. | +| `malformed_selection` | The selection could not be parsed. | +| `tag_load_failed` | Flag tags could not be loaded for this request. The full configuration is returned so that evaluation can continue. | + +If you route flag configuration requests through a proxy, see [Proxy Feature Flag SDK Traffic][7] for the header your proxy must pass through. + +#### Evaluate flags outside the selection + +When Datadog applies the selection, flags outside it are not loaded. Evaluating one of these flags returns the default value you supply, with the error code `FLAG_NOT_FOUND`: + +{{< code-block lang="javascript" >}} +// 'search-ranking' has no app:checkout-web tag and does not match checkout-* +const details = client.getBooleanDetails('search-ranking', false); + +console.log(details.value); // false (the supplied default) +console.log(details.errorCode); // 'FLAG_NOT_FOUND' +{{< /code-block >}} + +#### Initial configuration is not filtered + +`flagSelection` applies only to configuration that the SDK fetches. The SDK does not filter configuration you supply with `initialFlagsConfiguration` (see [Supply initial precomputed fallback data](#supply-initial-precomputed-fallback-data)), so flags in that configuration remain available even if they are outside the selection. + +#### Rules-based configuration + +`fetchRulesConfiguration()` from `@datadog/openfeature-browser/rules-based` accepts the same `flagSelection` option, with the same matching rules and limits. If the selection would make the request URL too long, the SDK does not send it and loads the full configuration. See [Browser Rules-Based Evaluation][4]. + ## Set the evaluation context Define who or what the flag evaluation applies to using an evaluation context. The evaluation context includes user or session information used to determine which flag variations should be returned. Reference these attributes in your targeting rules to control who sees each variant. @@ -247,81 +320,6 @@ The web provider also supports these optional settings: | `flagConfigurationFetch` | `globalThis.fetch` | Provide a Fetch-compatible implementation for flag configuration requests. | | `flagSelection` | unset | Load only the flags that match a set of tags or key patterns. See [Load a subset of flags](#load-a-subset-of-flags). | -### Load a subset of flags - - -In `@datadog/openfeature-browser` X.Y.Z and later, use `flagSelection` to load only the flags your application needs instead of every flag in the environment. Selecting a subset reduces the size of the flag configuration the SDK downloads and caches, which helps when an environment contains flags for many applications. - -`flagSelection` accepts two optional lists: - -`tags` -: Flag tags to match, such as `app:checkout-web`. A flag matches if it has any of the listed tags. Tags match exactly and are case-sensitive. - -`keyPatterns` -: Patterns to match against the whole flag key. `*` matches any sequence of characters, including none, anywhere in the pattern. Every other character, including `?`, `[`, `]`, `{`, and `}`, matches only itself. For example, `checkout-*` matches `checkout-banner` but not `new-checkout-banner`, and `*-checkout-*` matches `new-checkout-banner`. - -A flag loads if it matches any listed tag **or** any key pattern. In the following example, the SDK loads every flag tagged `app:checkout-web` and every flag whose key starts with `checkout-`: - -```javascript -import { DatadogProvider } from '@datadog/openfeature-browser'; - -const provider = new DatadogProvider({ - applicationId: '', - clientToken: '', - site: '{{< region-param key="dd_site" code="true" >}}', - env: '', - flagSelection: { - tags: ['app:checkout-web'], - keyPatterns: ['checkout-*'], - }, -}); -``` - -The selection is fixed when you create the provider. To load a different set of flags, create a new provider. - -
Add tags to your flags specifically for selection, such as app:checkout-web, rather than selecting by team tags. A flag's team tags can change when ownership changes, which would change the flags your application loads.
- -#### Limits and validation - -Before sending the selection, the SDK trims leading and trailing whitespace from each value, removes empty values and duplicates, and sorts each list. After this processing, the selection must meet these limits: - -- Each list (`tags` and `keyPatterns`) contains at most 31 values. -- Each tag and each key pattern is at most 200 bytes when encoded as UTF-8. - -If the selection is malformed or exceeds a limit, the SDK does not send it, logs an error to the browser console, and loads the full flag configuration. - -Datadog can also ignore a selection and return the full flag configuration. In that case, the response includes a `DD-Flag-Selection-Ignored` header with one of the following reasons, and the SDK logs an error to the browser console: - -| Reason | Meaning | -| --- | --- | -| `too_many_values` | A list contains more than 31 values. | -| `invalid_tag` | A tag is longer than 200 bytes. | -| `invalid_key_pattern` | A key pattern is longer than 200 bytes. | -| `malformed_selection` | The selection could not be parsed. | -| `tag_load_failed` | Flag tags could not be loaded for this request. The full configuration is returned so that evaluation can continue. | - -If you route flag configuration requests through a proxy, see [Proxy Feature Flag SDK Traffic][7] for the header your proxy must pass through. - -#### Evaluate flags outside the selection - -When Datadog applies the selection, flags outside it are not loaded. Evaluating one of these flags returns the default value you supply, with the error code `FLAG_NOT_FOUND`: - -{{< code-block lang="javascript" >}} -// 'search-ranking' has no app:checkout-web tag and does not match checkout-* -const details = client.getBooleanDetails('search-ranking', false); - -console.log(details.value); // false (the supplied default) -console.log(details.errorCode); // 'FLAG_NOT_FOUND' -{{< /code-block >}} - -#### Initial configuration is not filtered - -`flagSelection` applies only to configuration that the SDK fetches. The SDK does not filter configuration you supply with `initialFlagsConfiguration`, so flags in that configuration remain available even if they are outside the selection. - -#### Rules-based configuration - -`fetchRulesConfiguration()` from `@datadog/openfeature-browser/rules-based` accepts the same `flagSelection` option, with the same matching rules and limits. If the selection would make the request URL too long, the SDK does not send it and loads the full configuration. See [Browser Rules-Based Evaluation][4]. - ### Supply initial precomputed fallback data Use `initialFlagsConfiguration` to supply precomputed assignments, such as configuration delivered by your application at startup. In browser SDK 2.0.0, `DatadogProvider` still attempts a configuration fetch during initialization. If fetching fails and the supplied configuration matches the effective evaluation context, the provider uses it and reports `STALE` status. If the context does not match, the provider checks its persistent cache instead; without a matching fallback, initialization fails. From 940ea21a7dffa8dc6edae1eb335641d2817a2b30 Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Tue, 27 Oct 2026 17:27:37 +0000 Subject: [PATCH 03/12] Define the client in the flag selection example Add the OpenFeature.getClient() call to the Evaluate flags outside the selection example, since client is otherwise first defined in the later Get a client section. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 1 + 1 file changed, 1 insertion(+) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index ec7b2f3ca78b..da7ec2d7227d 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -143,6 +143,7 @@ If you route flag configuration requests through a proxy, see [Proxy Feature Fla When Datadog applies the selection, flags outside it are not loaded. Evaluating one of these flags returns the default value you supply, with the error code `FLAG_NOT_FOUND`: {{< code-block lang="javascript" >}} +const client = OpenFeature.getClient(); // 'search-ranking' has no app:checkout-web tag and does not match checkout-* const details = client.getBooleanDetails('search-ranking', false); From df13ffdb3f5c908edda4c3f580b36585de6fbe10 Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Tue, 27 Oct 2026 21:32:41 +0000 Subject: [PATCH 04/12] Use released openfeature-browser version for flag selection Set the minimum @datadog/openfeature-browser version to 2.2.0 and note that Datadog returns the full configuration without DD-Flag-Selection-Ignored when flag selection is not enabled for the organization. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index da7ec2d7227d..5088610c0bbf 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -87,8 +87,7 @@ const provider = new DatadogProvider({ ### Load a subset of flags - -In `@datadog/openfeature-browser` X.Y.Z and later, use `flagSelection` to load only the flags your application needs instead of every flag in the environment. Selecting a subset reduces the size of the flag configuration the SDK downloads and caches, which helps when an environment contains flags for many applications. Pass `flagSelection` to the provider when you create it; the selection is fixed for the provider's lifetime, so to load a different set of flags, create a new provider. +In `@datadog/openfeature-browser` 2.2.0 and later, use `flagSelection` to load only the flags your application needs instead of every flag in the environment. Selecting a subset reduces the size of the flag configuration the SDK downloads and caches, which helps when an environment contains flags for many applications. Pass `flagSelection` to the provider when you create it; the selection is fixed for the provider's lifetime, so to load a different set of flags, create a new provider. `flagSelection` accepts two optional lists: @@ -136,6 +135,8 @@ Datadog can also ignore a selection and return the full flag configuration. In t | `malformed_selection` | The selection could not be parsed. | | `tag_load_failed` | Flag tags could not be loaded for this request. The full configuration is returned so that evaluation can continue. | +If flag selection is not enabled for your organization, Datadog returns the full flag configuration without the `DD-Flag-Selection-Ignored` header, and the SDK does not log an error. + If you route flag configuration requests through a proxy, see [Proxy Feature Flag SDK Traffic][7] for the header your proxy must pass through. #### Evaluate flags outside the selection From 94fea486bc5a3bbcb3fa059fe20d7ee5e85cd4b6 Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Wed, 28 Oct 2026 14:10:37 +0000 Subject: [PATCH 05/12] Use neutral wording for the no-header case Flag selection is rolling out globally, so the no-header case no longer refers to per-organization enablement. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 5088610c0bbf..6129f6cb6074 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -135,7 +135,7 @@ Datadog can also ignore a selection and return the full flag configuration. In t | `malformed_selection` | The selection could not be parsed. | | `tag_load_failed` | Flag tags could not be loaded for this request. The full configuration is returned so that evaluation can continue. | -If flag selection is not enabled for your organization, Datadog returns the full flag configuration without the `DD-Flag-Selection-Ignored` header, and the SDK does not log an error. +If Datadog does not apply the selection, it can return the full flag configuration without the `DD-Flag-Selection-Ignored` header; the SDK does not log an error in that case. If you route flag configuration requests through a proxy, see [Proxy Feature Flag SDK Traffic][7] for the header your proxy must pass through. From c886cb7e10fcb18cd431676d7e19d3e310d00cb9 Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Wed, 28 Oct 2026 14:25:10 +0000 Subject: [PATCH 06/12] Describe flag selection as fully rolled out Remove the no-header case and state that flags outside the selection are not loaded. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 6129f6cb6074..dbb183d3904c 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -135,13 +135,11 @@ Datadog can also ignore a selection and return the full flag configuration. In t | `malformed_selection` | The selection could not be parsed. | | `tag_load_failed` | Flag tags could not be loaded for this request. The full configuration is returned so that evaluation can continue. | -If Datadog does not apply the selection, it can return the full flag configuration without the `DD-Flag-Selection-Ignored` header; the SDK does not log an error in that case. - If you route flag configuration requests through a proxy, see [Proxy Feature Flag SDK Traffic][7] for the header your proxy must pass through. #### Evaluate flags outside the selection -When Datadog applies the selection, flags outside it are not loaded. Evaluating one of these flags returns the default value you supply, with the error code `FLAG_NOT_FOUND`: +Flags outside the selection are not loaded. Evaluating one of these flags returns the default value you supply, with the error code `FLAG_NOT_FOUND`: {{< code-block lang="javascript" >}} const client = OpenFeature.getClient(); From c3594135cfb299ede556adef2abe55eadb0c7d0a Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Wed, 28 Oct 2026 14:43:59 +0000 Subject: [PATCH 07/12] Make the team-tags callout a warning Lead with the risk that team tags change with ownership, and render it as a WARNING callout. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index dbb183d3904c..9d684fd0b49f 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -114,7 +114,7 @@ const provider = new DatadogProvider({ }); ``` -
Add tags to your flags specifically for selection, such as app:checkout-web, rather than selecting by team tags. A flag's team tags can change when ownership changes, which would change the flags your application loads.
+
Team tags can change when ownership changes, which could change the flags your application loads. Add tags to your flags specifically for selection, such as app:checkout-web, rather than selecting by team tags.
#### Limits and validation From cea564fc13183aa23ccda5bda9b52316269e95ea Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Wed, 28 Oct 2026 14:45:09 +0000 Subject: [PATCH 08/12] Split flag selection limits into separate bullets List each limit on its own line so the 31-value limit is not read as a combined total. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 9d684fd0b49f..055db2c9f52e 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -120,10 +120,12 @@ const provider = new DatadogProvider({ Before sending the selection, the SDK trims leading and trailing whitespace from each value, removes empty values and duplicates, and sorts each list. After this processing, the selection must meet these limits: -- Each list (`tags` and `keyPatterns`) contains at most 31 values. -- Each tag and each key pattern is at most 200 bytes when encoded as UTF-8. +- `tags` contains at most 31 values. +- `keyPatterns` contains at most 31 values. +- Each tag is at most 200 bytes (UTF-8). +- Each key pattern is at most 200 bytes (UTF-8). -If the selection is malformed or exceeds a limit, the SDK does not send it, logs an error to the browser console, and loads the full flag configuration. +If the flag selection is malformed or exceeds a limit, the SDK does not send it in the flag configuration request, logs an error to the browser console, and loads the full flag configuration. Datadog can also ignore a selection and return the full flag configuration. In that case, the response includes a `DD-Flag-Selection-Ignored` header with one of the following reasons, and the SDK logs an error to the browser console: From ae4d37889f08d3704d5915a656fefaa71095f40f Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Wed, 28 Oct 2026 15:05:17 +0000 Subject: [PATCH 09/12] State the rules-based request URL limit Matches MAX_RULES_URL_BYTES and the too_many_values console error in @datadog/openfeature-browser 2.2.0. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 055db2c9f52e..201552593a7e 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -158,7 +158,7 @@ console.log(details.errorCode); // 'FLAG_NOT_FOUND' #### Rules-based configuration -`fetchRulesConfiguration()` from `@datadog/openfeature-browser/rules-based` accepts the same `flagSelection` option, with the same matching rules and limits. If the selection would make the request URL too long, the SDK does not send it and loads the full configuration. See [Browser Rules-Based Evaluation][4]. +`fetchRulesConfiguration()` from `@datadog/openfeature-browser/rules-based` accepts the same `flagSelection` option, with the same matching rules and limits. The request URL, including the encoded selection, must be at most 8,192 bytes. If it would be longer, the SDK does not send the selection, logs a `too_many_values` error to the browser console, and loads the full configuration. See [Browser Rules-Based Evaluation][4]. ## Set the evaluation context From 162be287419abc21a37e75bdc2cbf1aeb352a760 Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Wed, 28 Oct 2026 15:32:38 +0000 Subject: [PATCH 10/12] Clarify too_many_values, empty selections and the proxy header State that too_many_values also covers selections too long for one request, document that empty selections load the full configuration silently, and scope the Access-Control-Expose-Headers requirement to cross-origin proxies. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 4 +++- hugo/content/en/feature_flags/guide/proxy_sdk_traffic.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 201552593a7e..3c642f269259 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -125,13 +125,15 @@ Before sending the selection, the SDK trims leading and trailing whitespace from - Each tag is at most 200 bytes (UTF-8). - Each key pattern is at most 200 bytes (UTF-8). +If both lists are empty after this processing, the SDK sends no selection and loads the full flag configuration without logging an error. + If the flag selection is malformed or exceeds a limit, the SDK does not send it in the flag configuration request, logs an error to the browser console, and loads the full flag configuration. Datadog can also ignore a selection and return the full flag configuration. In that case, the response includes a `DD-Flag-Selection-Ignored` header with one of the following reasons, and the SDK logs an error to the browser console: | Reason | Meaning | | --- | --- | -| `too_many_values` | A list contains more than 31 values. | +| `too_many_values` | A list contains more than 31 values, or the selection is too long to send in one request. | | `invalid_tag` | A tag is longer than 200 bytes. | | `invalid_key_pattern` | A key pattern is longer than 200 bytes. | | `malformed_selection` | The selection could not be parsed. | diff --git a/hugo/content/en/feature_flags/guide/proxy_sdk_traffic.md b/hugo/content/en/feature_flags/guide/proxy_sdk_traffic.md index 21941be06c10..74030d554aff 100644 --- a/hugo/content/en/feature_flags/guide/proxy_sdk_traffic.md +++ b/hugo/content/en/feature_flags/guide/proxy_sdk_traffic.md @@ -203,7 +203,7 @@ DatadogBrowserFlagging.init({ }); {{< /code-block >}} -If you use [`flagSelection`][3] to load a subset of flags, return the `DD-Flag-Selection-Ignored` response header to the browser unchanged, and include it in the `Access-Control-Expose-Headers` response header. Datadog sets this header when it ignores a selection and returns the full flag configuration. If the browser cannot read the header, the full configuration still loads, but the SDK cannot report that the selection was ignored. +If you use [`flagSelection`][3] to load a subset of flags, return the `DD-Flag-Selection-Ignored` response header to the browser unchanged. If your proxy is on a different origin from your application, also list the header in the `Access-Control-Expose-Headers` response header. Datadog sets this header when it ignores a selection and returns the full flag configuration. If the browser cannot read the header, the full configuration still loads, but the SDK cannot report that the selection was ignored. ### Event upload proxy From 56fda8bacce2e0b15381903514ea0851fc46584c Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Wed, 28 Oct 2026 15:37:00 +0000 Subject: [PATCH 11/12] List flag selection console error messages Add the two console error templates the browser SDK logs when it does not send a flag selection or when Datadog ignores it. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 3c642f269259..703dcb626b5d 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -139,6 +139,13 @@ Datadog can also ignore a selection and return the full flag configuration. In t | `malformed_selection` | The selection could not be parsed. | | `tag_load_failed` | Flag tags could not be loaded for this request. The full configuration is returned so that evaluation can continue. | +The SDK logs these errors to the browser console: + +| Message | Cause | +| --- | --- | +| `Datadog Browser SDK: flagSelection was not sent (: ). Loading the full flag configuration.` | The selection is malformed or exceeds a limit. | +| `Datadog Browser SDK: flagSelection was ignored by the server (). Loaded the full flag configuration.` | Datadog ignored the selection. See the reasons above. | + If you route flag configuration requests through a proxy, see [Proxy Feature Flag SDK Traffic][7] for the header your proxy must pass through. #### Evaluate flags outside the selection From 2b8c706eca179243deadc0ebe7bdf7ef55c4eb6c Mon Sep 17 00:00:00 2001 From: Mark Cai Date: Wed, 28 Oct 2026 15:37:33 +0000 Subject: [PATCH 12/12] Simplify the initialFlagsConfiguration note State in one sentence that flagSelection does not filter configuration supplied with initialFlagsConfiguration. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5.5 --- hugo/content/en/feature_flags/client/javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 703dcb626b5d..cfae4fcdf9f9 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -163,7 +163,7 @@ console.log(details.errorCode); // 'FLAG_NOT_FOUND' #### Initial configuration is not filtered -`flagSelection` applies only to configuration that the SDK fetches. The SDK does not filter configuration you supply with `initialFlagsConfiguration` (see [Supply initial precomputed fallback data](#supply-initial-precomputed-fallback-data)), so flags in that configuration remain available even if they are outside the selection. +`flagSelection` does not filter configuration you supply with [`initialFlagsConfiguration`](#supply-initial-precomputed-fallback-data); the SDK uses it as provided. #### Rules-based configuration