From a1b96ad0218821aebb013e5b48764c9ae5211ab2 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Fri, 28 Aug 2026 23:19:59 +0000 Subject: [PATCH 01/12] docs: document opt-in assignment request reliability Document zero-default assignment timeout and retry controls for supported client SDKs, including composable transport examples. Defer React Native until released native dependencies are available. Environment: Datadog workspace --- .../en/feature_flags/client/android.md | 29 +++++++++++++++- .../en/feature_flags/client/flutter.md | 33 +++++++++++++++++++ hugo/content/en/feature_flags/client/ios.md | 25 ++++++++++++++ .../en/feature_flags/client/javascript.md | 16 +++++++++ hugo/content/en/feature_flags/client/unity.md | 23 +++++++++++++ .../getting_started/feature_flags/_index.md | 8 +++-- 6 files changed, 131 insertions(+), 3 deletions(-) diff --git a/hugo/content/en/feature_flags/client/android.md b/hugo/content/en/feature_flags/client/android.md index d7d7981c013..fc55714d41d 100644 --- a/hugo/content/en/feature_flags/client/android.md +++ b/hugo/content/en/feature_flags/client/android.md @@ -300,12 +300,39 @@ The `Flags.enable()` API accepts optional configuration with the options listed {{< code-block lang="kotlin" >}} val config = FlagsConfiguration.Builder() - // configure options here + .assignmentRequestTimeout(2_000L) + .assignmentRequestRetryCount(2) .build() Flags.enable(config) {{< /code-block >}} +`assignmentRequestTimeout(timeoutMs)` +: Timeout in milliseconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. + +`assignmentRequestRetryCount(retryCount)` +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; HTTP 429 responses are not retried. + +
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
+ +For lower-level transport control, supply an assignment-only OkHttp call factory: + +{{< code-block lang="kotlin" >}} +import okhttp3.OkHttpClient + +val assignmentClient = OkHttpClient.Builder() + // Add assignment-specific proxy, TLS, or interceptors here. + .build() + +val config = FlagsConfiguration.Builder() + .assignmentRequestCallFactory(assignmentClient) + .assignmentRequestTimeout(2_000L) + .assignmentRequestRetryCount(2) + .build() +{{< /code-block >}} + +The SDK still constructs the URL, method, body, and authentication headers. The scalar timeout and retry policies compose on top of calls created by the supplied factory. Exposure and evaluation uploads continue to use the SDK transport, and the application retains ownership of the supplied factory and its resources. + `trackExposures()` : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. If you only need local evaluation without telemetry, you can disable it with: `trackExposures(false)`. diff --git a/hugo/content/en/feature_flags/client/flutter.md b/hugo/content/en/feature_flags/client/flutter.md index 0e06d30b1b1..e9f58e4b4ee 100644 --- a/hugo/content/en/feature_flags/client/flutter.md +++ b/hugo/content/en/feature_flags/client/flutter.md @@ -289,6 +289,8 @@ print(details.error?.code); {{< code-block lang="dart" >}} DatadogFlagsConfiguration( datadogConfig: datadogConfig, + assignmentRequestTimeout: const Duration(seconds: 2), + assignmentRequestRetryCount: 2, trackExposures: true, trackEvaluations: true, evaluationFlushInterval: const Duration(seconds: 10), @@ -296,6 +298,35 @@ DatadogFlagsConfiguration( ); {{< /code-block >}} +`assignmentRequestTimeout` +: Timeout for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive duration to enable the timeout; `Duration.zero` leaves it disabled. + +`assignmentRequestRetryCount` +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; HTTP 429 responses are not retried. + +
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
+ +For lower-level transport control, compose an assignment-only HTTP client: + +{{< code-block lang="dart" >}} +import 'package:http/http.dart' as http; + +final assignmentClient = withAssignmentRequestRetry( + withAssignmentRequestTimeout( + http.Client(), + const Duration(seconds: 2), + ), + 2, +); + +final config = DatadogFlagsConfiguration( + datadogConfig: datadogConfig, + assignmentRequestHttpClient: assignmentClient, +); +{{< /code-block >}} + +A supplied `assignmentRequestHttpClient` is used verbatim and replaces the scalar timeout and retry settings. The helpers buffer the complete response, create a fresh request for each retry, and apply only to assignment requests. The application owns and closes the supplied client after disabling Feature Flags. + `trackExposures` : When `true` (default), the SDK records exposure events for successful evaluations whose assignments are marked for logging. Set to `false` to disable exposure tracking. @@ -326,6 +357,8 @@ final configuration = DatadogConfiguration( )..addPlugin( const DatadogFlagsPluginConfiguration( flagsConfiguration: DatadogFlagsConfiguration( + assignmentRequestTimeout: Duration(seconds: 2), + assignmentRequestRetryCount: 2, trackExposures: true, trackEvaluations: true, ), diff --git a/hugo/content/en/feature_flags/client/ios.md b/hugo/content/en/feature_flags/client/ios.md index 88a9cb6bc83..e83ccd43e3b 100644 --- a/hugo/content/en/feature_flags/client/ios.md +++ b/hugo/content/en/feature_flags/client/ios.md @@ -444,9 +444,34 @@ The `Flags.enable()` API accepts optional configuration with options listed belo {{< code-block lang="swift" >}} var config = Flags.Configuration() +config.assignmentRequestTimeout = 2.0 +config.assignmentRequestRetryCount = 2 Flags.enable(with: config) {{< /code-block >}} +`assignmentRequestTimeout` +: Timeout in seconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. + +`assignmentRequestRetryCount` +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; HTTP 429 responses are not retried. + +
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
+ +For lower-level transport control, compose an assignment-only fetch implementation: + +{{< code-block lang="swift" >}} +let assignmentFetch = Flags.AssignmentRequestFetch + .urlSession() + .withTimeout(2) + .withRetry(2) + +var config = Flags.Configuration() +config.assignmentRequestFetch = assignmentFetch +Flags.enable(with: config) +{{< /code-block >}} + +The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` is used verbatim and replaces the scalar timeout and retry settings. In the example, placing `withTimeout` inside `withRetry` gives every attempt its own two-second timeout. The custom transport applies only to assignment requests. + `trackExposures` : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. If you only need local evaluation without telemetry, you can disable this option. diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index f6876136dd6..4b3f6038e12 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -226,6 +226,22 @@ The web provider also supports these optional settings: | `flaggingProxy` | unset | Fetch flags through a proxy instead of `site`. | | `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. | + +### Bound flag configuration requests + +The browser provider does not add a timeout or retries by default. Use `withTimeout` and `withRetry` to bound each request attempt and retry transient failures: + +{{< code-block lang="javascript" >}} +import { DatadogProvider, withRetry, withTimeout } from '@datadog/openfeature-browser'; + +const provider = new DatadogProvider({ + // Other provider options... + flagConfigurationFetch: withRetry(withTimeout(globalThis.fetch, 2_000), 2), +}); +{{< /code-block >}} + +In this example, each attempt has a two-second timeout and `2` allows two retries after the initial request. The timeout includes downloading the response body. Set the timeout or retry count to `0` to disable that behavior; retry counts from `0` to `10` are accepted. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. `flagConfigurationFetch` applies only to flag configuration requests; it does not affect exposure, aggregated flag evaluation, or RUM telemetry requests. ## Override flags in your browser diff --git a/hugo/content/en/feature_flags/client/unity.md b/hugo/content/en/feature_flags/client/unity.md index 270aa8ec788..65060d2b164 100644 --- a/hugo/content/en/feature_flags/client/unity.md +++ b/hugo/content/en/feature_flags/client/unity.md @@ -203,12 +203,35 @@ The `DdFlags.Enable()` API accepts optional configuration with options listed be {{< code-block lang="csharp" >}} DdFlags.Enable(new FlagsConfiguration( + assignmentRequestTimeoutSeconds: 2, + assignmentRequestRetryCount: 2, trackExposures: true, trackEvaluations: true, evaluationFlushIntervalSeconds: 10.0f )); {{< /code-block >}} +`assignmentRequestTimeoutSeconds` +: Timeout in seconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. + +`assignmentRequestRetryCount` +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; HTTP 429 responses are not retried. + +
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
+ +For lower-level transport control, compose an assignment-only transport: + +{{< code-block lang="csharp" >}} +var assignmentTransport = AssignmentRequestTransports.Default + .WithTimeout(2) + .WithRetry(2); + +DdFlags.Enable(new FlagsConfiguration( + assignmentRequestTransport: assignmentTransport)); +{{< /code-block >}} + +A supplied `assignmentRequestTransport` is used verbatim and replaces the scalar timeout and retry settings. The helpers use fully buffered immutable responses, create a fresh native request for each retry, and apply only to assignment requests. The SDK owns its native requests; the application retains ownership of a custom transport and its resources. + `trackExposures` : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. Set to `false` to disable exposure tracking. diff --git a/hugo/content/en/getting_started/feature_flags/_index.md b/hugo/content/en/getting_started/feature_flags/_index.md index b5ad7b7b206..1224471d182 100644 --- a/hugo/content/en/getting_started/feature_flags/_index.md +++ b/hugo/content/en/getting_started/feature_flags/_index.md @@ -86,6 +86,8 @@ You can set up Feature Flags automatically with the Client SDKs do not add a flag assignment request timeout or retry by default, so the underlying platform transport remains authoritative. Configure a bounded timeout explicitly when you need a predictable initialization limit, and opt in to retries when appropriate. The browser example below applies a one-second timeout to each attempt and explicitly retries once. The supported SDK guides describe their timeout options and composable transport APIs. + {{< tabs >}} {{% tab "JavaScript browser" %}} @@ -100,7 +102,7 @@ Then, add the following to your project to initialize the SDK: {{< site-region region="gov,gov2" >}}
Browser Feature Flags are not supported for the selected Datadog site ({{< region-param key="dd_site_name" >}}).
{{< /site-region >}} {{< code-block lang="javascript" >}} -import { DatadogProvider } from '@datadog/openfeature-browser'; +import { DatadogProvider, withRetry, withTimeout } from '@datadog/openfeature-browser'; import { OpenFeature } from '@openfeature/web-sdk'; // Initialize the provider @@ -111,7 +113,9 @@ const provider = new DatadogProvider({ site: '{{< region-param key="dd_site" code="true" >}}', env: '', // Same environment normally passed to the RUM SDK service: '', - version: '1.0.0' + version: '1.0.0', + // Bound each configuration request and explicitly opt in to one retry. + flagConfigurationFetch: withRetry(withTimeout(globalThis.fetch, 1_000), 1) }); // Set the provider From 030aba59578b1c918e736d9f81fb2957934d7f5b Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Fri, 28 Aug 2026 23:28:24 +0000 Subject: [PATCH 02/12] docs: recommend bounded assignment timeouts in setup --- .../en/feature_flags/client/android.md | 19 ++++++++++++++----- .../en/feature_flags/client/flutter.md | 16 ++++++++++++---- hugo/content/en/feature_flags/client/ios.md | 14 +++++++++----- .../en/feature_flags/client/javascript.md | 10 ++++++---- hugo/content/en/feature_flags/client/unity.md | 8 +++++--- .../getting_started/feature_flags/_index.md | 8 ++++---- 6 files changed, 50 insertions(+), 25 deletions(-) diff --git a/hugo/content/en/feature_flags/client/android.md b/hugo/content/en/feature_flags/client/android.md index fc55714d41d..ab6f8985a18 100644 --- a/hugo/content/en/feature_flags/client/android.md +++ b/hugo/content/en/feature_flags/client/android.md @@ -40,8 +40,12 @@ val configuration = Configuration.Builder( .build() Datadog.initialize(this, configuration, TrackingConsent.GRANTED) -// 3. Enable Feature Flags -Flags.enable() +// 3. Enable Feature Flags with a bounded assignment request timeout +Flags.enable( + FlagsConfiguration.Builder() + .assignmentRequestTimeout(1_500L) + .build() +) // 4. Create and set up the OpenFeature provider val provider = FlagsClient.Builder().build().asOpenFeatureProvider() @@ -98,8 +102,13 @@ After initializing Datadog, enable `Flags` to attach it to the current Datadog A {{< code-block lang="kotlin" >}} import com.datadog.android.flags.Flags +import com.datadog.android.flags.FlagsConfiguration + +val flagsConfiguration = FlagsConfiguration.Builder() + .assignmentRequestTimeout(1_500L) + .build() -Flags.enable() +Flags.enable(flagsConfiguration) {{< /code-block >}} You can also pass a configuration object; see [Advanced configuration](#advanced-configuration). @@ -300,7 +309,7 @@ The `Flags.enable()` API accepts optional configuration with the options listed {{< code-block lang="kotlin" >}} val config = FlagsConfiguration.Builder() - .assignmentRequestTimeout(2_000L) + .assignmentRequestTimeout(1_500L) .assignmentRequestRetryCount(2) .build() @@ -326,7 +335,7 @@ val assignmentClient = OkHttpClient.Builder() val config = FlagsConfiguration.Builder() .assignmentRequestCallFactory(assignmentClient) - .assignmentRequestTimeout(2_000L) + .assignmentRequestTimeout(1_500L) .assignmentRequestRetryCount(2) .build() {{< /code-block >}} diff --git a/hugo/content/en/feature_flags/client/flutter.md b/hugo/content/en/feature_flags/client/flutter.md index e9f58e4b4ee..828122ced50 100644 --- a/hugo/content/en/feature_flags/client/flutter.md +++ b/hugo/content/en/feature_flags/client/flutter.md @@ -86,7 +86,13 @@ final configuration = DatadogConfiguration( rumConfiguration: DatadogRumConfiguration( applicationId: '', ), -)..addPlugin(const DatadogFlagsPluginConfiguration()); +)..addPlugin( + const DatadogFlagsPluginConfiguration( + flagsConfiguration: DatadogFlagsConfiguration( + assignmentRequestTimeout: Duration(milliseconds: 1500), + ), + ), + ); await DatadogSdk.instance.initialize(configuration, TrackingConsent.granted); {{< /code-block >}} @@ -126,6 +132,7 @@ final datadogFlags = DatadogFlags.instance; await datadogFlags.enable( configuration: DatadogFlagsConfiguration( + assignmentRequestTimeout: const Duration(milliseconds: 1500), datadogConfig: const DatadogFlagsConfig( clientToken: '', env: '', @@ -289,7 +296,7 @@ print(details.error?.code); {{< code-block lang="dart" >}} DatadogFlagsConfiguration( datadogConfig: datadogConfig, - assignmentRequestTimeout: const Duration(seconds: 2), + assignmentRequestTimeout: const Duration(milliseconds: 1500), assignmentRequestRetryCount: 2, trackExposures: true, trackEvaluations: true, @@ -314,7 +321,7 @@ import 'package:http/http.dart' as http; final assignmentClient = withAssignmentRequestRetry( withAssignmentRequestTimeout( http.Client(), - const Duration(seconds: 2), + const Duration(milliseconds: 1500), ), 2, ); @@ -357,7 +364,7 @@ final configuration = DatadogConfiguration( )..addPlugin( const DatadogFlagsPluginConfiguration( flagsConfiguration: DatadogFlagsConfiguration( - assignmentRequestTimeout: Duration(seconds: 2), + assignmentRequestTimeout: Duration(milliseconds: 1500), assignmentRequestRetryCount: 2, trackExposures: true, trackEvaluations: true, @@ -424,6 +431,7 @@ Future initializeFlags() async { await datadogFlags.enable( configuration: DatadogFlagsConfiguration( + assignmentRequestTimeout: const Duration(milliseconds: 1500), datadogConfig: const DatadogFlagsConfig( clientToken: '', env: '', diff --git a/hugo/content/en/feature_flags/client/ios.md b/hugo/content/en/feature_flags/client/ios.md index e83ccd43e3b..2f677a21aa1 100644 --- a/hugo/content/en/feature_flags/client/ios.md +++ b/hugo/content/en/feature_flags/client/ios.md @@ -99,7 +99,9 @@ After initializing Datadog, enable `Flags` to attach it to the current Datadog i {{< code-block lang="swift" >}} import DatadogFlags -Flags.enable() +var flagsConfiguration = Flags.Configuration() +flagsConfiguration.assignmentRequestTimeout = 1.5 +Flags.enable(with: flagsConfiguration) {{< /code-block >}} You can also pass a configuration object; see [Advanced configuration](#advanced-configuration). @@ -328,7 +330,9 @@ Datadog.initialize( trackingConsent: .granted ) -Flags.enable() +var flagsConfiguration = Flags.Configuration() +flagsConfiguration.assignmentRequestTimeout = 1.5 +Flags.enable(with: flagsConfiguration) let context = MutableContext(targetingKey: "user-123") let provider = DatadogProvider() @@ -444,7 +448,7 @@ The `Flags.enable()` API accepts optional configuration with options listed belo {{< code-block lang="swift" >}} var config = Flags.Configuration() -config.assignmentRequestTimeout = 2.0 +config.assignmentRequestTimeout = 1.5 config.assignmentRequestRetryCount = 2 Flags.enable(with: config) {{< /code-block >}} @@ -462,7 +466,7 @@ For lower-level transport control, compose an assignment-only fetch implementati {{< code-block lang="swift" >}} let assignmentFetch = Flags.AssignmentRequestFetch .urlSession() - .withTimeout(2) + .withTimeout(1.5) .withRetry(2) var config = Flags.Configuration() @@ -470,7 +474,7 @@ config.assignmentRequestFetch = assignmentFetch Flags.enable(with: config) {{< /code-block >}} -The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` is used verbatim and replaces the scalar timeout and retry settings. In the example, placing `withTimeout` inside `withRetry` gives every attempt its own two-second timeout. The custom transport applies only to assignment requests. +The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` is used verbatim and replaces the scalar timeout and retry settings. In the example, placing `withTimeout` inside `withRetry` gives every attempt its own 1.5-second timeout. The custom transport applies only to assignment requests. `trackExposures` : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. If you only need local evaluation without telemetry, you can disable this option. diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 4b3f6038e12..180dfa63978 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -53,7 +53,7 @@ Create a `DatadogProvider` instance with your Datadog credentials. For live Brow {{< site-region region="gov,gov2" >}}
Browser Feature Flags are not supported for the selected Datadog site ({{< region-param key="dd_site_name" >}}).
{{< /site-region >}} ```javascript -import { DatadogProvider } from '@datadog/openfeature-browser'; +import { DatadogProvider, withTimeout } from '@datadog/openfeature-browser'; import { OpenFeature } from '@openfeature/web-sdk'; const provider = new DatadogProvider({ @@ -65,6 +65,7 @@ const provider = new DatadogProvider({ clientToken: '', site: '{{< region-param key="dd_site" code="true" >}}', env: '', + flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500), }); ``` @@ -170,7 +171,7 @@ console.log(details.errorCode); // Error code, if evaluation failed Here's a complete example showing how to set up and use Datadog Feature Flags in a JavaScript application: ```javascript -import { DatadogProvider } from '@datadog/openfeature-browser'; +import { DatadogProvider, withTimeout } from '@datadog/openfeature-browser'; import { OpenFeature } from '@openfeature/web-sdk'; // Initialize the Datadog provider @@ -179,6 +180,7 @@ const provider = new DatadogProvider({ clientToken: '', site: '{{< region-param key="dd_site" code="true" >}}', env: '', + flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500), }); // Set the evaluation context @@ -237,11 +239,11 @@ import { DatadogProvider, withRetry, withTimeout } from '@datadog/openfeature-br const provider = new DatadogProvider({ // Other provider options... - flagConfigurationFetch: withRetry(withTimeout(globalThis.fetch, 2_000), 2), + flagConfigurationFetch: withRetry(withTimeout(globalThis.fetch, 1_500), 2), }); {{< /code-block >}} -In this example, each attempt has a two-second timeout and `2` allows two retries after the initial request. The timeout includes downloading the response body. Set the timeout or retry count to `0` to disable that behavior; retry counts from `0` to `10` are accepted. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. `flagConfigurationFetch` applies only to flag configuration requests; it does not affect exposure, aggregated flag evaluation, or RUM telemetry requests. +In this example, each attempt has a 1.5-second timeout and `2` allows two retries after the initial request. The timeout includes downloading the response body. Set the timeout or retry count to `0` to disable that behavior; retry counts from `0` to `10` are accepted. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. `flagConfigurationFetch` applies only to flag configuration requests; it does not affect exposure, aggregated flag evaluation, or RUM telemetry requests. ## Override flags in your browser diff --git a/hugo/content/en/feature_flags/client/unity.md b/hugo/content/en/feature_flags/client/unity.md index 65060d2b164..4e8f116a9ed 100644 --- a/hugo/content/en/feature_flags/client/unity.md +++ b/hugo/content/en/feature_flags/client/unity.md @@ -52,7 +52,9 @@ After initializing Datadog, enable `Flags` to attach it to the current Datadog U {{< code-block lang="csharp" >}} using Datadog.Unity.Flags; -DdFlags.Enable(); +DdFlags.Enable(new FlagsConfiguration( + assignmentRequestTimeoutSeconds: 1, + assignmentRequestRetryCount: 0)); {{< /code-block >}} You can also pass a configuration object; see [Advanced configuration](#advanced-configuration). @@ -203,7 +205,7 @@ The `DdFlags.Enable()` API accepts optional configuration with options listed be {{< code-block lang="csharp" >}} DdFlags.Enable(new FlagsConfiguration( - assignmentRequestTimeoutSeconds: 2, + assignmentRequestTimeoutSeconds: 1, assignmentRequestRetryCount: 2, trackExposures: true, trackEvaluations: true, @@ -223,7 +225,7 @@ For lower-level transport control, compose an assignment-only transport: {{< code-block lang="csharp" >}} var assignmentTransport = AssignmentRequestTransports.Default - .WithTimeout(2) + .WithTimeout(1) .WithRetry(2); DdFlags.Enable(new FlagsConfiguration( diff --git a/hugo/content/en/getting_started/feature_flags/_index.md b/hugo/content/en/getting_started/feature_flags/_index.md index 1224471d182..61ed1aec327 100644 --- a/hugo/content/en/getting_started/feature_flags/_index.md +++ b/hugo/content/en/getting_started/feature_flags/_index.md @@ -86,7 +86,7 @@ You can set up Feature Flags automatically with the Client SDKs do not add a flag assignment request timeout or retry by default, so the underlying platform transport remains authoritative. Configure a bounded timeout explicitly when you need a predictable initialization limit, and opt in to retries when appropriate. The browser example below applies a one-second timeout to each attempt and explicitly retries once. The supported SDK guides describe their timeout options and composable transport APIs. +
Client SDKs do not add a flag assignment request timeout or retry by default, so the underlying platform transport remains authoritative. Configure a bounded timeout of at most 1,500 milliseconds for predictable initialization, and opt in to retries only when appropriate. The browser example below applies a 1,500-millisecond timeout with no retries. The supported SDK guides describe their timeout options and composable transport APIs.
{{< tabs >}} {{% tab "JavaScript browser" %}} @@ -102,7 +102,7 @@ Then, add the following to your project to initialize the SDK: {{< site-region region="gov,gov2" >}}
{{< /site-region >}} {{< code-block lang="javascript" >}} -import { DatadogProvider, withRetry, withTimeout } from '@datadog/openfeature-browser'; +import { DatadogProvider, withTimeout } from '@datadog/openfeature-browser'; import { OpenFeature } from '@openfeature/web-sdk'; // Initialize the provider @@ -114,8 +114,8 @@ const provider = new DatadogProvider({ env: '', // Same environment normally passed to the RUM SDK service: '', version: '1.0.0', - // Bound each configuration request and explicitly opt in to one retry. - flagConfigurationFetch: withRetry(withTimeout(globalThis.fetch, 1_000), 1) + // Bound each configuration request to 1,500 milliseconds. + flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500) }); // Set the provider From ea974122e6ab5b99ae7c381a389835ffc18e4892 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Wed, 2 Sep 2026 19:31:01 -0400 Subject: [PATCH 03/12] docs: use the shipped browser fetch option --- hugo/content/en/feature_flags/client/javascript.md | 10 +++++----- .../content/en/getting_started/feature_flags/_index.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 180dfa63978..f6a868954ee 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -65,7 +65,7 @@ const provider = new DatadogProvider({ clientToken: '', site: '{{< region-param key="dd_site" code="true" >}}', env: '', - flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500), + fetch: withTimeout(globalThis.fetch, 1_500), }); ``` @@ -180,7 +180,7 @@ const provider = new DatadogProvider({ clientToken: '', site: '{{< region-param key="dd_site" code="true" >}}', env: '', - flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500), + fetch: withTimeout(globalThis.fetch, 1_500), }); // Set the evaluation context @@ -228,7 +228,7 @@ The web provider also supports these optional settings: | `flaggingProxy` | unset | Fetch flags through a proxy instead of `site`. | | `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. | +| `fetch` | `globalThis.fetch` | Provide a Fetch-compatible implementation for flag configuration requests. | ### Bound flag configuration requests @@ -239,11 +239,11 @@ import { DatadogProvider, withRetry, withTimeout } from '@datadog/openfeature-br const provider = new DatadogProvider({ // Other provider options... - flagConfigurationFetch: withRetry(withTimeout(globalThis.fetch, 1_500), 2), + fetch: withRetry(withTimeout(globalThis.fetch, 1_500), 2), }); {{< /code-block >}} -In this example, each attempt has a 1.5-second timeout and `2` allows two retries after the initial request. The timeout includes downloading the response body. Set the timeout or retry count to `0` to disable that behavior; retry counts from `0` to `10` are accepted. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. `flagConfigurationFetch` applies only to flag configuration requests; it does not affect exposure, aggregated flag evaluation, or RUM telemetry requests. +In this example, each attempt has a 1.5-second timeout and `2` allows two retries after the initial request. The timeout includes downloading the response body. Set the timeout or retry count to `0` to disable that behavior; retry counts from `0` to `10` are accepted. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. `fetch` applies only to flag configuration requests; it does not affect exposure, aggregated flag evaluation, or RUM telemetry requests. ## Override flags in your browser diff --git a/hugo/content/en/getting_started/feature_flags/_index.md b/hugo/content/en/getting_started/feature_flags/_index.md index 61ed1aec327..89cc286f510 100644 --- a/hugo/content/en/getting_started/feature_flags/_index.md +++ b/hugo/content/en/getting_started/feature_flags/_index.md @@ -115,7 +115,7 @@ const provider = new DatadogProvider({ service: '', version: '1.0.0', // Bound each configuration request to 1,500 milliseconds. - flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500) + fetch: withTimeout(globalThis.fetch, 1_500) }); // Set the provider From b220ec92267de3fcc94f8f12eb0b130c007a8014 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Wed, 2 Sep 2026 22:46:50 -0400 Subject: [PATCH 04/12] docs: correct browser retry and timeout limits --- 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 f6a868954ee..6eebd355e5c 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -243,7 +243,7 @@ const provider = new DatadogProvider({ }); {{< /code-block >}} -In this example, each attempt has a 1.5-second timeout and `2` allows two retries after the initial request. The timeout includes downloading the response body. Set the timeout or retry count to `0` to disable that behavior; retry counts from `0` to `10` are accepted. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. `fetch` applies only to flag configuration requests; it does not affect exposure, aggregated flag evaluation, or RUM telemetry requests. +In this example, each attempt has a 1.5-second timeout and `2` allows two retries after the initial request. The timeout includes downloading the response body. A retry count of `0` disables retries. Both helpers require non-negative integers. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. `fetch` applies only to flag configuration requests; it does not affect exposure, aggregated flag evaluation, or RUM telemetry requests. ## Override flags in your browser From 783375e17fdef5d9210d629e3060e13699087da7 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Wed, 2 Sep 2026 23:28:09 -0400 Subject: [PATCH 05/12] docs: clarify assignment transport behavior --- hugo/content/en/feature_flags/client/android.md | 2 +- hugo/content/en/feature_flags/client/ios.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hugo/content/en/feature_flags/client/android.md b/hugo/content/en/feature_flags/client/android.md index ab6f8985a18..b40a2d6f5d0 100644 --- a/hugo/content/en/feature_flags/client/android.md +++ b/hugo/content/en/feature_flags/client/android.md @@ -320,7 +320,7 @@ Flags.enable(config) : Timeout in milliseconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. `assignmentRequestRetryCount(retryCount)` -: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; HTTP 429 responses are not retried. +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; canceled calls and HTTP 429 responses are not retried.
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
diff --git a/hugo/content/en/feature_flags/client/ios.md b/hugo/content/en/feature_flags/client/ios.md index 2f677a21aa1..5e10767ed4d 100644 --- a/hugo/content/en/feature_flags/client/ios.md +++ b/hugo/content/en/feature_flags/client/ios.md @@ -474,7 +474,7 @@ config.assignmentRequestFetch = assignmentFetch Flags.enable(with: config) {{< /code-block >}} -The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` is used verbatim and replaces the scalar timeout and retry settings. In the example, placing `withTimeout` inside `withRetry` gives every attempt its own 1.5-second timeout. The custom transport applies only to assignment requests. +The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` is used verbatim and replaces the scalar timeout and retry settings. In the example, placing `withTimeout` inside `withRetry` gives every attempt its own 1.5-second timeout. A `withTimeout` value of `0` causes an immediate timeout. The custom transport applies only to assignment requests. `trackExposures` : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. If you only need local evaluation without telemetry, you can disable this option. From added44dd5aff99a60ea109fe84d07e2a6b8c869 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Wed, 2 Sep 2026 23:54:29 -0400 Subject: [PATCH 06/12] docs: address assignment reliability feedback --- hugo/content/en/feature_flags/client/flutter.md | 1 + hugo/content/en/feature_flags/client/javascript.md | 8 +++++++- hugo/content/en/getting_started/feature_flags/_index.md | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/hugo/content/en/feature_flags/client/flutter.md b/hugo/content/en/feature_flags/client/flutter.md index 828122ced50..e944e4d4144 100644 --- a/hugo/content/en/feature_flags/client/flutter.md +++ b/hugo/content/en/feature_flags/client/flutter.md @@ -316,6 +316,7 @@ DatadogFlagsConfiguration( For lower-level transport control, compose an assignment-only HTTP client: {{< code-block lang="dart" >}} +import 'package:datadog_flags/datadog_flags.dart'; import 'package:http/http.dart' as http; final assignmentClient = withAssignmentRequestRetry( diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 6eebd355e5c..47531de38d0 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -243,7 +243,13 @@ const provider = new DatadogProvider({ }); {{< /code-block >}} -In this example, each attempt has a 1.5-second timeout and `2` allows two retries after the initial request. The timeout includes downloading the response body. A retry count of `0` disables retries. Both helpers require non-negative integers. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. `fetch` applies only to flag configuration requests; it does not affect exposure, aggregated flag evaluation, or RUM telemetry requests. +`withTimeout(fetch, timeoutMs)` +: Sets the timeout in milliseconds for each request attempt, including the complete response-body download. Set the timeout to `0` to disable the timer. Accepted values are non-negative integers up to `2_147_483_647`. + +`withRetry(fetch, retryCount)` +: Sets the number of retries after the initial request. Set the retry count to `0` to disable retries. Accepted values are integers from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. + +
The `fetch` option applies only to flag configuration requests. It does not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
## Override flags in your browser diff --git a/hugo/content/en/getting_started/feature_flags/_index.md b/hugo/content/en/getting_started/feature_flags/_index.md index 89cc286f510..8209aaf30c2 100644 --- a/hugo/content/en/getting_started/feature_flags/_index.md +++ b/hugo/content/en/getting_started/feature_flags/_index.md @@ -86,7 +86,7 @@ You can set up Feature Flags automatically with the Client SDKs do not add a flag assignment request timeout or retry by default, so the underlying platform transport remains authoritative. Configure a bounded timeout of at most 1,500 milliseconds for predictable initialization, and opt in to retries only when appropriate. The browser example below applies a 1,500-millisecond timeout with no retries. The supported SDK guides describe their timeout options and composable transport APIs. + {{< tabs >}} {{% tab "JavaScript browser" %}} From 526cfe1a3079db1b4f4a221a5c2379cff959d875 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 3 Sep 2026 12:52:45 -0400 Subject: [PATCH 07/12] docs: align assignment request retry policies --- hugo/content/en/feature_flags/client/android.md | 8 +++++--- hugo/content/en/feature_flags/client/flutter.md | 2 +- hugo/content/en/feature_flags/client/ios.md | 15 +++++++++++++-- .../content/en/feature_flags/client/javascript.md | 4 +++- hugo/content/en/feature_flags/client/unity.md | 2 +- .../en/getting_started/feature_flags/_index.md | 2 +- 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/hugo/content/en/feature_flags/client/android.md b/hugo/content/en/feature_flags/client/android.md index b40a2d6f5d0..95a9aed7b41 100644 --- a/hugo/content/en/feature_flags/client/android.md +++ b/hugo/content/en/feature_flags/client/android.md @@ -317,14 +317,16 @@ Flags.enable(config) {{< /code-block >}} `assignmentRequestTimeout(timeoutMs)` -: Timeout in milliseconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. +: Timeout in milliseconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. Negative values are coerced to `0`. `assignmentRequestRetryCount(retryCount)` -: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; canceled calls and HTTP 429 responses are not retried. +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Values outside the range from `0` to `10` are coerced to the nearest bound. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Canceled calls, HTTP 429, generic I/O errors, permanent protocol errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. + +With retries enabled, network time can reach `(retryCount + 1) * timeoutMs`, plus retry delays. When the timeout is `0`, the HTTP transport supplies the time bound and may allow an unlimited duration.
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
-For lower-level transport control, supply an assignment-only OkHttp call factory: +For lower-level transport control, supply an assignment-only OkHttp call factory. Add OkHttp as a direct application dependency when you use this option: {{< code-block lang="kotlin" >}} import okhttp3.OkHttpClient diff --git a/hugo/content/en/feature_flags/client/flutter.md b/hugo/content/en/feature_flags/client/flutter.md index e944e4d4144..7b59fe63f7f 100644 --- a/hugo/content/en/feature_flags/client/flutter.md +++ b/hugo/content/en/feature_flags/client/flutter.md @@ -309,7 +309,7 @@ DatadogFlagsConfiguration( : Timeout for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive duration to enable the timeout; `Duration.zero` leaves it disabled. `assignmentRequestRetryCount` -: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; HTTP 429 responses are not retried. +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, generic I/O errors, permanent protocol errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried.
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
diff --git a/hugo/content/en/feature_flags/client/ios.md b/hugo/content/en/feature_flags/client/ios.md index 5e10767ed4d..92b2849d6a5 100644 --- a/hugo/content/en/feature_flags/client/ios.md +++ b/hugo/content/en/feature_flags/client/ios.md @@ -457,7 +457,7 @@ Flags.enable(with: config) : Timeout in seconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. `assignmentRequestRetryCount` -: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; HTTP 429 responses are not retried. +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, unknown URL errors, permanent URL errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried.
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
@@ -474,7 +474,18 @@ config.assignmentRequestFetch = assignmentFetch Flags.enable(with: config) {{< /code-block >}} -The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` is used verbatim and replaces the scalar timeout and retry settings. In the example, placing `withTimeout` inside `withRetry` gives every attempt its own 1.5-second timeout. A `withTimeout` value of `0` causes an immediate timeout. The custom transport applies only to assignment requests. +The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` replaces the scalar timeout and retry settings. The SDK accepts at most one completion from the supplied fetch for each request and validates the HTTP response status. The custom transport applies only to assignment requests. + +In the example, `withTimeout` is inside `withRetry`. Therefore, each attempt has its own 1.5-second timeout. Reverse the wrappers to use one 1.5-second timeout for the initial request and all retries: + +{{< code-block lang="swift" >}} +let assignmentFetch = Flags.AssignmentRequestFetch + .urlSession() + .withRetry(2) + .withTimeout(1.5) +{{< /code-block >}} + +A `withTimeout` value of `0` disables the timer. `trackExposures` : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. If you only need local evaluation without telemetry, you can disable this option. diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 47531de38d0..516e2e423c0 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -247,7 +247,9 @@ const provider = new DatadogProvider({ : Sets the timeout in milliseconds for each request attempt, including the complete response-body download. Set the timeout to `0` to disable the timer. Accepted values are non-negative integers up to `2_147_483_647`. `withRetry(fetch, retryCount)` -: Sets the number of retries after the initial request. Set the retry count to `0` to disable retries. Accepted values are integers from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; caller cancellation and HTTP 429 responses are not retried. +: Sets the number of retries after the initial request. Set the retry count to `0` to disable retries. Accepted values are integers from `0` to `10`. Retries cover Fetch `TypeError` failures, timeout errors, HTTP 408, and HTTP 5xx responses. Caller cancellation and HTTP 429 responses are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. Browsers report network, CORS, and CSP failures as `TypeError`, so the wrapper cannot separate these causes. + +In the example, `withTimeout` is inside `withRetry`. Therefore, each attempt has its own 1,500-millisecond timeout.
The `fetch` option applies only to flag configuration requests. It does not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
diff --git a/hugo/content/en/feature_flags/client/unity.md b/hugo/content/en/feature_flags/client/unity.md index 4e8f116a9ed..591176981c9 100644 --- a/hugo/content/en/feature_flags/client/unity.md +++ b/hugo/content/en/feature_flags/client/unity.md @@ -217,7 +217,7 @@ DdFlags.Enable(new FlagsConfiguration( : Timeout in seconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. `assignmentRequestRetryCount` -: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover network errors, timeouts, HTTP 408, and HTTP 5xx responses; HTTP 429 responses are not retried. +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, generic I/O errors, permanent protocol errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried.
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
diff --git a/hugo/content/en/getting_started/feature_flags/_index.md b/hugo/content/en/getting_started/feature_flags/_index.md index 8209aaf30c2..a3c0d0d55b5 100644 --- a/hugo/content/en/getting_started/feature_flags/_index.md +++ b/hugo/content/en/getting_started/feature_flags/_index.md @@ -86,7 +86,7 @@ You can set up Feature Flags automatically with the Client SDKs do not add a flag assignment request timeout or retry by default, so the underlying platform transport remains authoritative. Configure a timeout of at most 1,500 milliseconds when initialization must finish within a known period. Add retries to tolerate transient network errors, timeouts, HTTP 408, or HTTP 5xx responses. See the client SDK guides for platform-specific timeout, retry, and transport APIs. +
Client SDKs do not add a flag assignment request timeout or retry by default, so the underlying platform transport remains authoritative. Configure a timeout of at most 1,500 milliseconds when initialization must finish within a known period. Retries cover transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. They use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid Retry-After value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. Mobile SDKs do not retry cancellation, HTTP 429, generic I/O errors, permanent protocol errors, or TLS failures. Browser Fetch reports several failures as TypeError and cannot separate these causes. See the client SDK guides for platform-specific timeout, retry, and transport APIs.
{{< tabs >}} {{% tab "JavaScript browser" %}} From 324773a7ffddef9bd9fcae416341e240e7cedb13 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 3 Sep 2026 13:24:33 -0400 Subject: [PATCH 08/12] docs: clarify Android timeout composition --- hugo/content/en/feature_flags/client/android.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugo/content/en/feature_flags/client/android.md b/hugo/content/en/feature_flags/client/android.md index 95a9aed7b41..45ff69a3222 100644 --- a/hugo/content/en/feature_flags/client/android.md +++ b/hugo/content/en/feature_flags/client/android.md @@ -317,7 +317,7 @@ Flags.enable(config) {{< /code-block >}} `assignmentRequestTimeout(timeoutMs)` -: Timeout in milliseconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. Negative values are coerced to `0`. +: Timeout in milliseconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. Negative values are coerced to `0`. When the HTTP call already has a nonzero timeout, the shorter timeout applies. `assignmentRequestRetryCount(retryCount)` : Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Values outside the range from `0` to `10` are coerced to the nearest bound. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Canceled calls, HTTP 429, generic I/O errors, permanent protocol errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. From c97477dab87bedd1a9950ea57362b3f965afa962 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 3 Sep 2026 14:36:33 -0400 Subject: [PATCH 09/12] docs: use browser flag configuration fetch option --- hugo/content/en/feature_flags/client/javascript.md | 10 +++++----- .../content/en/getting_started/feature_flags/_index.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hugo/content/en/feature_flags/client/javascript.md b/hugo/content/en/feature_flags/client/javascript.md index 516e2e423c0..e350d2c5a10 100644 --- a/hugo/content/en/feature_flags/client/javascript.md +++ b/hugo/content/en/feature_flags/client/javascript.md @@ -65,7 +65,7 @@ const provider = new DatadogProvider({ clientToken: '', site: '{{< region-param key="dd_site" code="true" >}}', env: '', - fetch: withTimeout(globalThis.fetch, 1_500), + flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500), }); ``` @@ -180,7 +180,7 @@ const provider = new DatadogProvider({ clientToken: '', site: '{{< region-param key="dd_site" code="true" >}}', env: '', - fetch: withTimeout(globalThis.fetch, 1_500), + flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500), }); // Set the evaluation context @@ -228,7 +228,7 @@ The web provider also supports these optional settings: | `flaggingProxy` | unset | Fetch flags through a proxy instead of `site`. | | `customHeaders` | unset | Add headers to flag-fetch requests. | | `overwriteRequestHeaders` | `false` | Replace default request headers with `customHeaders`. | -| `fetch` | `globalThis.fetch` | Provide a Fetch-compatible implementation for flag configuration requests. | +| `flagConfigurationFetch` | `globalThis.fetch` | Provide a Fetch-compatible implementation for flag configuration requests. | ### Bound flag configuration requests @@ -239,7 +239,7 @@ import { DatadogProvider, withRetry, withTimeout } from '@datadog/openfeature-br const provider = new DatadogProvider({ // Other provider options... - fetch: withRetry(withTimeout(globalThis.fetch, 1_500), 2), + flagConfigurationFetch: withRetry(withTimeout(globalThis.fetch, 1_500), 2), }); {{< /code-block >}} @@ -251,7 +251,7 @@ const provider = new DatadogProvider({ In the example, `withTimeout` is inside `withRetry`. Therefore, each attempt has its own 1,500-millisecond timeout. -
The `fetch` option applies only to flag configuration requests. It does not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
+
The `flagConfigurationFetch` option applies only to flag configuration requests. It does not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
## Override flags in your browser diff --git a/hugo/content/en/getting_started/feature_flags/_index.md b/hugo/content/en/getting_started/feature_flags/_index.md index a3c0d0d55b5..846204dbf91 100644 --- a/hugo/content/en/getting_started/feature_flags/_index.md +++ b/hugo/content/en/getting_started/feature_flags/_index.md @@ -115,7 +115,7 @@ const provider = new DatadogProvider({ service: '', version: '1.0.0', // Bound each configuration request to 1,500 milliseconds. - fetch: withTimeout(globalThis.fetch, 1_500) + flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500) }); // Set the provider From 5e59f39356718311cecefffc6c76a4746fa06611 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 3 Sep 2026 14:36:39 -0400 Subject: [PATCH 10/12] docs: describe iOS assignment request bounds --- hugo/content/en/feature_flags/client/ios.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hugo/content/en/feature_flags/client/ios.md b/hugo/content/en/feature_flags/client/ios.md index 92b2849d6a5..bc59165f57f 100644 --- a/hugo/content/en/feature_flags/client/ios.md +++ b/hugo/content/en/feature_flags/client/ios.md @@ -454,10 +454,10 @@ Flags.enable(with: config) {{< /code-block >}} `assignmentRequestTimeout` -: Timeout in seconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. +: Timeout in seconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive, finite value to enable the timeout. A value of `0`, a negative value, or a non-finite value disables it. Values greater than `2_147_483.647` seconds are reduced to this maximum. `assignmentRequestRetryCount` -: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, unknown URL errors, permanent URL errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Values outside the range from `0` to `10` are reduced to the nearest bound. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, unknown URL errors, permanent URL errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried.
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
From 325c289f86ad643c05fc8184d9cbad2999f4e01e Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 3 Sep 2026 14:36:45 -0400 Subject: [PATCH 11/12] docs: document Android custom call requirements --- hugo/content/en/feature_flags/client/android.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hugo/content/en/feature_flags/client/android.md b/hugo/content/en/feature_flags/client/android.md index 45ff69a3222..3258501248b 100644 --- a/hugo/content/en/feature_flags/client/android.md +++ b/hugo/content/en/feature_flags/client/android.md @@ -328,6 +328,12 @@ With retries enabled, network time can reach `(retryCount + 1) * timeoutMs`, plu For lower-level transport control, supply an assignment-only OkHttp call factory. Add OkHttp as a direct application dependency when you use this option: +{{< code-block lang="groovy" filename="build.gradle" >}} +dependencies { + implementation "com.squareup.okhttp3:okhttp:4.12.0" +} +{{< /code-block >}} + {{< code-block lang="kotlin" >}} import okhttp3.OkHttpClient @@ -342,7 +348,7 @@ val config = FlagsConfiguration.Builder() .build() {{< /code-block >}} -The SDK still constructs the URL, method, body, and authentication headers. The scalar timeout and retry policies compose on top of calls created by the supplied factory. Exposure and evaluation uploads continue to use the SDK transport, and the application retains ownership of the supplied factory and its resources. +The SDK still constructs the URL, method, body, and authentication headers. The scalar timeout and retry policies compose on top of calls created by the supplied factory. When the assignment timeout is positive, the factory must return calls that provide and honor a configurable `Call.timeout()`. A call that returns `Timeout.NONE` fails before execution. Exposure and evaluation uploads continue to use the SDK transport. The application retains ownership of the supplied factory and its resources. `trackExposures()` : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. If you only need local evaluation without telemetry, you can disable it with: `trackExposures(false)`. From b802ff09f8fde88ec476c27de405c17b3d039192 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 3 Sep 2026 17:21:55 -0400 Subject: [PATCH 12/12] docs: clarify assignment retry duration and ownership --- hugo/content/en/feature_flags/client/android.md | 4 ++-- hugo/content/en/feature_flags/client/ios.md | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/hugo/content/en/feature_flags/client/android.md b/hugo/content/en/feature_flags/client/android.md index 3258501248b..16e8f5e68ec 100644 --- a/hugo/content/en/feature_flags/client/android.md +++ b/hugo/content/en/feature_flags/client/android.md @@ -320,9 +320,9 @@ Flags.enable(config) : Timeout in milliseconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. Negative values are coerced to `0`. When the HTTP call already has a nonzero timeout, the shorter timeout applies. `assignmentRequestRetryCount(retryCount)` -: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Values outside the range from `0` to `10` are coerced to the nearest bound. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Canceled calls, HTTP 429, generic I/O errors, permanent protocol errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Values outside the range from `0` to `10` are coerced to the nearest bound. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Canceled calls, HTTP 429, generic I/O errors, permanent protocol errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. The SDK reads `Retry-After` only for HTTP 503. A valid value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. -With retries enabled, network time can reach `(retryCount + 1) * timeoutMs`, plus retry delays. When the timeout is `0`, the HTTP transport supplies the time bound and may allow an unlimited duration. +The SDK manages the configured retry count and creates a new HTTP call for each attempt. The timeout applies to each attempt. Total network duration can reach `(retryCount + 1) * timeoutMs`, plus retry delays. When the timeout is `0`, the HTTP transport supplies the time bound and may allow an unlimited duration.
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
diff --git a/hugo/content/en/feature_flags/client/ios.md b/hugo/content/en/feature_flags/client/ios.md index bc59165f57f..6d56e8a7163 100644 --- a/hugo/content/en/feature_flags/client/ios.md +++ b/hugo/content/en/feature_flags/client/ios.md @@ -457,7 +457,9 @@ Flags.enable(with: config) : Timeout in seconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive, finite value to enable the timeout. A value of `0`, a negative value, or a non-finite value disables it. Values greater than `2_147_483.647` seconds are reduced to this maximum. `assignmentRequestRetryCount` -: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Values outside the range from `0` to `10` are reduced to the nearest bound. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, unknown URL errors, permanent URL errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. +: Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Values outside the range from `0` to `10` are reduced to the nearest bound. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, unknown URL errors, permanent URL errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. The SDK reads `Retry-After` only for HTTP 503. A valid value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. + +The scalar timeout applies to each attempt. Total duration includes all attempts and all retry delays.
Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.
@@ -474,7 +476,13 @@ config.assignmentRequestFetch = assignmentFetch Flags.enable(with: config) {{< /code-block >}} -The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` replaces the scalar timeout and retry settings. The SDK accepts at most one completion from the supplied fetch for each request and validates the HTTP response status. The custom transport applies only to assignment requests. +The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` replaces the scalar timeout and retry settings. The SDK accepts at most one completion from the supplied fetch for each request and validates the HTTP response status. The custom transport applies only to assignment requests. The caller retains ownership of a supplied `URLSession` and other custom transport resources. The SDK does not invalidate or close them. + +`withTimeout(timeout)` +: Adds a timeout that includes the complete response-body download. A positive, finite value enables the timeout. A nonpositive or non-finite value leaves the transport unchanged. Values greater than `2_147_483.647` seconds are reduced to this maximum. + +`withRetry(retryCount)` +: Adds SDK-managed retries after the initial attempt. Values outside the range from `0` to `10` are reduced to the nearest bound. The retry policy matches `assignmentRequestRetryCount`. The SDK reads `Retry-After` only for HTTP 503. In the example, `withTimeout` is inside `withRetry`. Therefore, each attempt has its own 1.5-second timeout. Reverse the wrappers to use one 1.5-second timeout for the initial request and all retries: @@ -485,7 +493,7 @@ let assignmentFetch = Flags.AssignmentRequestFetch .withTimeout(1.5) {{< /code-block >}} -A `withTimeout` value of `0` disables the timer. +With this reversed order, one timeout covers all attempts and retry delays. With the original order, total duration includes each attempt timeout and all retry delays. `trackExposures` : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. If you only need local evaluation without telemetry, you can disable this option.