diff --git a/config/_default/menus/main.en.yaml b/config/_default/menus/main.en.yaml index 6194637fcd4..239a68675c6 100644 --- a/config/_default/menus/main.en.yaml +++ b/config/_default/menus/main.en.yaml @@ -6348,6 +6348,41 @@ menu: parent: feature_flags identifier: feature_flags_server weight: 2 + - name: .NET + url: feature_flags/server/dotnet + parent: feature_flags_server + identifier: feature_flags_server_dotnet + weight: 201 + - name: Go + url: feature_flags/server/go + parent: feature_flags_server + identifier: feature_flags_server_go + weight: 202 + - name: Java + url: feature_flags/server/java + parent: feature_flags_server + identifier: feature_flags_server_java + weight: 203 + - name: Node.js + url: feature_flags/server/nodejs + parent: feature_flags_server + identifier: feature_flags_server_nodejs + weight: 204 + - name: PHP + url: feature_flags/server/php + parent: feature_flags_server + identifier: feature_flags_server_php + weight: 205 + - name: Python + url: feature_flags/server/python + parent: feature_flags_server + identifier: feature_flags_server_python + weight: 206 + - name: Ruby + url: feature_flags/server/ruby + parent: feature_flags_server + identifier: feature_flags_server_ruby + weight: 207 - name: Concepts url: feature_flags/concepts parent: feature_flags @@ -6403,66 +6438,51 @@ menu: parent: feature_flags_concepts identifier: feature_flags_concepts_approvals weight: 321 + - name: Use Cases + url: feature_flags/use_cases + parent: feature_flags + identifier: feature_flags_use_cases + weight: 4 + - name: Progressive Rollouts and Canaries + url: feature_flags/use_cases/progressive_rollouts + parent: feature_flags_use_cases + identifier: feature_flags_use_cases_progressive_rollouts + weight: 401 + - name: Kill Switches + url: feature_flags/use_cases/kill_switches + parent: feature_flags_use_cases + identifier: feature_flags_use_cases_kill_switches + weight: 402 + - name: Dynamic Configuration + url: feature_flags/use_cases/dynamic_configuration + parent: feature_flags_use_cases + identifier: feature_flags_use_cases_dynamic_configuration + weight: 403 - name: Implementation Patterns url: feature_flags/implementation_patterns parent: feature_flags identifier: feature_flags_implementation_patterns - weight: 4 + weight: 5 - name: OpenTelemetry url: feature_flags/implementation_patterns/opentelemetry parent: feature_flags_implementation_patterns identifier: feature_flags_implementation_patterns_opentelemetry - weight: 401 + weight: 501 - name: Serverless url: feature_flags/implementation_patterns/serverless parent: feature_flags_implementation_patterns identifier: feature_flags_implementation_patterns_serverless - weight: 402 + weight: 502 - name: MCP Server url: feature_flags/feature_flag_mcp_server parent: feature_flags identifier: feature_flags_mcp_server - weight: 8 - - name: .NET - url: feature_flags/server/dotnet - parent: feature_flags_server - identifier: feature_flags_server_dotnet - weight: 201 - - name: Go - url: feature_flags/server/go - parent: feature_flags_server - identifier: feature_flags_server_go - weight: 202 - - name: Java - url: feature_flags/server/java - parent: feature_flags_server - identifier: feature_flags_server_java - weight: 203 - - name: Node.js - url: feature_flags/server/nodejs - parent: feature_flags_server - identifier: feature_flags_server_nodejs - weight: 204 - - name: PHP - url: feature_flags/server/php - parent: feature_flags_server - identifier: feature_flags_server_php - weight: 205 - - name: Python - url: feature_flags/server/python - parent: feature_flags_server - identifier: feature_flags_server_python - weight: 206 - - name: Ruby - url: feature_flags/server/ruby - parent: feature_flags_server - identifier: feature_flags_server_ruby - weight: 207 + weight: 6 - name: Guides url: feature_flags/guide parent: feature_flags identifier: feature_flags_guide - weight: 9 + weight: 7 - name: Source Code Integration url: source_code/ pre: dev-code diff --git a/content/en/feature_flags/_index.md b/content/en/feature_flags/_index.md index 2112834d578..32357800af7 100644 --- a/content/en/feature_flags/_index.md +++ b/content/en/feature_flags/_index.md @@ -11,6 +11,9 @@ further_reading: - link: "/getting_started/feature_flags/" tag: "Documentation" text: "Getting started with Feature Flags" +- link: "/feature_flags/use_cases/" + tag: "Documentation" + text: "Feature Flags Use Cases" - link: "/feature_flags/concepts/" tag: "Documentation" text: "Learn the core concepts of Feature Flags" diff --git a/content/en/feature_flags/use_cases/_index.md b/content/en/feature_flags/use_cases/_index.md new file mode 100644 index 00000000000..3172f0322bb --- /dev/null +++ b/content/en/feature_flags/use_cases/_index.md @@ -0,0 +1,14 @@ +--- +title: Use Cases +description: Common use cases for Datadog Feature Flags. +--- + +Feature flags support distinct rollout and control patterns. Pick the use case that matches your goal: limit release risk with gradual rollouts, stop broken features fast during incidents, or change application settings without a code deployment. + +Each page below walks through why teams choose that pattern and how to set it up in Datadog. + +{{< whatsnext desc=" " >}} + {{< nextlink href="/feature_flags/use_cases/progressive_rollouts" >}}Progressive Rollouts and Canaries{{< /nextlink >}} + {{< nextlink href="/feature_flags/use_cases/kill_switches" >}}Kill Switches{{< /nextlink >}} + {{< nextlink href="/feature_flags/use_cases/dynamic_configuration" >}}Dynamic Configuration{{< /nextlink >}} +{{< /whatsnext >}} diff --git a/content/en/feature_flags/use_cases/dynamic_configuration.md b/content/en/feature_flags/use_cases/dynamic_configuration.md new file mode 100644 index 00000000000..03e2106073f --- /dev/null +++ b/content/en/feature_flags/use_cases/dynamic_configuration.md @@ -0,0 +1,28 @@ +--- +title: Dynamic Configuration +description: Change application behavior with feature flag configuration instead of code deployments. +--- + +A feature flag becomes **dynamic configuration** when you store application settings in its variants instead of code. Rather than hardcoding a value and deploying a new build to change it, you update the variant in Datadog and your application reads the new value on the next SDK refresh. Product, marketing, and operations teams can update strings, numbers, or JSON-backed settings directly, without involving engineering. + +## Set up a JSON configuration flag + +1. Navigate to [**Create Feature Flag**][1]. +2. In the **Variants** section, set the variant type to **JSON**. +3. Optionally add a [JSON Schema][2] to validate variant values. Datadog recommends adding a schema to catch invalid variant values early. +4. Add variants with values that conform to the schema, and give each a descriptive name. + +{{< img src="feature_flags/dynamic_config_json_variants.png" alt="The Variants section of the create flag form showing a JSON schema and two variants: All items price asc and In stock top rated." style="width:100%;" >}} + +## Next steps + +After your flag is set up, you can use it as a foundation for more advanced workflows: + +- **Target by segment**: Use targeting rules to serve different configuration values to different user segments — for example, serving different sort defaults by region or subscription tier. +- **Roll out gradually**: Use a [progressive rollout][3] to incrementally expose subjects to a new configuration variant, and roll back immediately if something goes wrong. +- **Run an experiment**: Add an [experiment][4] targeting rule to serve different variants to different groups and measure the impact on your key metrics. + +[1]: https://app.datadoghq.com/feature-flags/create +[2]: https://json-schema.org/overview/what-is-jsonschema +[3]: /feature_flags/use_cases/progressive_rollouts/ +[4]: /experiments/ diff --git a/content/en/feature_flags/use_cases/kill_switches.md b/content/en/feature_flags/use_cases/kill_switches.md new file mode 100644 index 00000000000..a17d2aad61f --- /dev/null +++ b/content/en/feature_flags/use_cases/kill_switches.md @@ -0,0 +1,99 @@ +--- +title: Kill Switches +description: Use Boolean feature flags as kill switches to disable features instantly without redeploying. +further_reading: +- link: "/feature_flags/client/" + tag: "Documentation" + text: "Client-Side SDKs" +--- + +A **kill switch** is a Boolean feature flag where the default state is **on** (`true`). The feature runs normally until you enact the kill switch by adding a targeting rule that serves `false`. + +Use a kill switch when you need to turn off risky or broken functionality in seconds from Datadog, without waiting for a deploy. During incidents, that gives operations and engineering a fast path to stop customer impact while the rest of the application keeps running. + +## Set up a kill switch + +### Step 1: Create a Boolean flag + +1. Navigate to [**Create Feature Flag**][1]. +2. Set the variant type to **Boolean**. +3. Mark the flag as **Permanent**. +4. In the **Variants** section, click **Make Default** next to the **True** variant. This sets `true` as the value served to all subjects by default. + + {{< img src="feature_flags/kill_switch_make_default.png" alt="The Variants section of the create flag form, showing Boolean variants with Make Default highlighted next to the True variant." style="width:90%;" >}} + +5. Save the flag. + +### Step 2: Evaluate the flag in your application + +Wrap the feature code with a Boolean evaluation and a fallback of `true`. The fallback keeps the feature enabled if the flag configuration is unavailable: + +{{< programming-lang-wrapper langs="javascript,python,go" >}} + +{{< programming-lang lang="javascript" >}} + +```javascript +import { OpenFeature } from '@openfeature/web-sdk'; + +const client = OpenFeature.getClient(); +const fallback = true; +const showFeature = await client.getBooleanValue('my-kill-switch-flag', fallback); + +if (showFeature) { + // Feature code here +} +``` + +{{< /programming-lang >}} + +{{< programming-lang lang="python" >}} + +```python +enabled = client.get_boolean_value("my-kill-switch-flag", True, eval_ctx) +if enabled: + # Feature code here + pass +``` + +{{< /programming-lang >}} + +{{< programming-lang lang="go" >}} + +```go +enabled, _ := client.BooleanValue(ctx, "my-kill-switch-flag", true, evalCtx) +if enabled { + // Feature code here +} +``` + +{{< /programming-lang >}} + +{{< /programming-lang-wrapper >}} + +Deploy the application with the flag check in place before enabling the flag in production. + +### Step 3: Enable the flag + +Enable the flag in the target environment. No targeting rules are needed at this stage — the flag serves `true` (feature on) to all subjects by default. + +### Step 4: Enact the kill switch + +When you need to disable the feature — for example, during a regression or to stop a third-party integration from sending requests — add a targeting rule that serves `false`: + +1. Navigate to the flag in Datadog. +2. Add a targeting rule to serve `false` to the affected subjects. +3. Save the rule. The SDK serves `false` on the next configuration refresh, and the feature code path stops running for the affected subjects. + +## Best practices + +- Use a fallback of `true` so the feature stays enabled if the flag is unavailable — you don't want the feature to accidentally turn off due to a connectivity issue. +- Mark the flag as **Permanent**. Kill switches are intended to be long-lived, and marking them permanent prevents them from being flagged as [stale][2]. +- Test the kill switch in staging before relying on it in production. +- Use evaluation tracking to confirm the flag state during an incident. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://app.datadoghq.com/feature-flags/create +[2]: /feature_flags/concepts/stale_flags/ diff --git a/content/en/feature_flags/use_cases/progressive_rollouts.md b/content/en/feature_flags/use_cases/progressive_rollouts.md new file mode 100644 index 00000000000..628e2ad5a89 --- /dev/null +++ b/content/en/feature_flags/use_cases/progressive_rollouts.md @@ -0,0 +1,60 @@ +--- +title: Progressive Rollouts and Canaries +description: Gradually roll out feature flags on a schedule with optional guardrail metrics for canary releases. +--- + +**Progressive rollouts** release new functionality gradually by incrementing the percentage of subjects exposed to the feature over time. **Canaries** are progressive rollouts that monitor guardrail metrics and automatically pause or stop when they detect regressions. + +## Progressive rollouts + +### Configure a progressive rollout + +1. Navigate to your feature flag and open **Targeting Rules & Rollouts** for the target environment. +2. Click **Add Targeting Rule** and select **Add Rollout Steps** to create a multistep rollout. +3. Configure rollout steps: + - Customize the percentage for each step, and add or delete steps as needed. + - Change the delay between steps for a slower or faster rollout. + - Click **Split Traffic** to roll out multiple variants at the same time. + +{{< img src="getting_started/feature_flags/create-progressive-rollout.png" alt="Multistep progressive rollout configuration." style="width:100%;" >}} + +### Start and control the rollout + +1. **Enable** the flag in the environment so SDKs evaluate your targeting rules. +2. Click **Start Rollout** to kick off the progressive rollout. + +{{< img src="getting_started/feature_flags/start-progressive-rollout.png" alt="Multistep progressive rollout display." style="width:100%;" >}} + +After the rollout starts: + +- Click **Pause Rollout** to stop progress temporarily. +- Click **Stop Rollout** to revert all progress on the rollout. + +Monitor progress with evaluation tracking and configure notifications for rollout events. + +## Canaries + +A canary is a progressive rollout that includes **guardrail metrics**. Guardrail metrics measure standard key performance indicators (KPIs) such as error rate and long task count. + +### How canaries work + +When guardrail metrics are configured, the rollout monitors metrics in both groups: + +- **Treatment**: Subjects receiving the variant you are rolling out +- **Control**: Subjects not receiving the treatment variant + +When the canary detects a statistically significant change in any guardrail metric, it automatically **pauses** or **stops** the rollout. + +### Configure a canary rollout + +1. Create a progressive rollout targeting rule as described above. +2. Add guardrail metrics to the rollout configuration. +3. Choose whether guardrail failures should pause or stop the rollout. + +{{< img src="getting_started/feature_flags/canary-rollout-config.png" alt="Canary rollout configuration showing rollout steps with guardrail metrics and a control variant." style="width:90%;" >}} + +## Best practices + +- Configure notifications on the flag to be alerted when the rollout starts, pauses, or stops. +- For canaries, notifications fire when a guardrail metric pauses or stops the rollout — configure these before starting the rollout so you're alerted immediately if a regression is detected. +- Use evaluation tracking to monitor how many subjects are receiving each variant as the rollout progresses. diff --git a/static/images/feature_flags/dynamic_config_json_variants.png b/static/images/feature_flags/dynamic_config_json_variants.png new file mode 100644 index 00000000000..542b75b7d79 Binary files /dev/null and b/static/images/feature_flags/dynamic_config_json_variants.png differ diff --git a/static/images/feature_flags/kill_switch_make_default.png b/static/images/feature_flags/kill_switch_make_default.png new file mode 100644 index 00000000000..a7a038dc6e1 Binary files /dev/null and b/static/images/feature_flags/kill_switch_make_default.png differ diff --git a/static/images/getting_started/feature_flags/canary-rollout-config.png b/static/images/getting_started/feature_flags/canary-rollout-config.png new file mode 100644 index 00000000000..9cdb842ffbe Binary files /dev/null and b/static/images/getting_started/feature_flags/canary-rollout-config.png differ diff --git a/static/images/getting_started/feature_flags/create-progressive-rollout.png b/static/images/getting_started/feature_flags/create-progressive-rollout.png new file mode 100644 index 00000000000..3da793e27cc Binary files /dev/null and b/static/images/getting_started/feature_flags/create-progressive-rollout.png differ diff --git a/static/images/getting_started/feature_flags/start-progressive-rollout.png b/static/images/getting_started/feature_flags/start-progressive-rollout.png new file mode 100644 index 00000000000..fa4c3b01011 Binary files /dev/null and b/static/images/getting_started/feature_flags/start-progressive-rollout.png differ