---
title: Getting Started with Feature Flags
description: >-
  Manage feature delivery with integrated observability, real-time metrics, and
  OpenFeature-compatible gradual rollouts.
breadcrumbs: Docs > Getting Started > Getting Started with Feature Flags
---

# Getting Started with Feature Flags

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

## Overview{% #overview %}

Datadog feature flags offer a powerful, integrated way to manage feature delivery, with built-in observability and seamless integration across the platform.

- **Real-time metrics:** Understand who's receiving each variant, as well as how your flag impacts the health & performance of your application—all in real time.

- **Supports common flag types:** Use Boolean, string, integer, numeric (float/double), or JSON variants. JavaScript SDKs use `getNumberValue()` for both integer and numeric variants, while Java, Swift, Kotlin, and Python expose separate integer and floating-point evaluation methods.

- **Built for experimentation:** Target specific audiences for A/B tests, roll out features gradually with canary releases, and automatically roll back when regressions are detected.

- **OpenFeature compatible:** Built on the OpenFeature standard, ensuring compatibility with existing OpenFeature implementations and providing a vendor-neutral approach to feature flag management.

## Feature Flags SDKs{% #feature-flags-sdks %}

This guide uses the JavaScript browser SDK as an example. You can integrate Datadog Feature Flags into any application using one of the following SDKs:

### Client-side SDKs{% #client-side-sdks %}

### Server-side SDKs{% #server-side-sdks %}

## Configure your environments{% #configure-your-environments %}

Your organization likely already has pre-configured environments for Development, Staging, and Production. For details on environment queries, production marking, and managing environments, see [Environments](https://docs.datadoghq.com/feature_flags/concepts/environments.md).

## Create your first feature flag{% #create-your-first-feature-flag %}

### Step 1: Import and initialize the SDK{% #step-1-import-and-initialize-the-sdk %}

Choose the SDK that matches where the flag is evaluated and initialize the Datadog Feature Flags provider.

{% tab title="JavaScript browser" %}
Install `@datadog/openfeature-browser`, `@openfeature/web-sdk`, and `@openfeature/core` as dependencies in your project:

```bash
yarn add @datadog/openfeature-browser @openfeature/web-sdk @openfeature/core
```

Then, add the following to your project to initialize the SDK:

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %}
Browser Feature Flags are not supported for the selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md) ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

```javascript
import { DatadogProvider } from '@datadog/openfeature-browser';
import { OpenFeature } from '@openfeature/web-sdk';

// Initialize the provider
const provider = new DatadogProvider({
    // Required client-side Datadog credentials
    applicationId: '<APPLICATION_ID>',
    clientToken: '<CLIENT_TOKEN>',
    site: '<code class="js-region-param region-param" data-region-param="dd_site"></code>',
    env: '<YOUR_ENV>', // Same environment normally passed to the RUM SDK
    service: '<SERVICE_NAME>',
    version: '1.0.0'
});

// Set the provider
await OpenFeature.setProviderAndWait(provider);
```

{% alert level="info" %}
The browser SDK emits three independent telemetry streams, all enabled by default. `enableExposureLogging` sends per-evaluation exposure events to the exposures intake. `enableFlagEvaluationTracking` sends aggregated evaluation telemetry to the flag-evaluation intake. `enableRumFeatureFlagTracking` attaches flag evaluations to RUM events and is the setting that can affect RUM usage. Disable only the stream you do not need.
{% /alert %}

{% /tab %}

{% tab title="Node.js server" %}
Install `dd-trace` and the OpenFeature server SDK:

```bash
npm install dd-trace @openfeature/server-sdk
```

Enable the provider with environment variables:

```bash
# Required: Enable the feature flags provider
DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true

# Optional: Enable flag evaluation metrics
DD_METRICS_OTEL_ENABLED=true
```

Or enable the provider in code:

```javascript
import { OpenFeature } from '@openfeature/server-sdk'
import tracer from 'dd-trace';

tracer.init({
  experimental: {
    flaggingProvider: {
      enabled: true,
    }
  }
});

OpenFeature.setProvider(tracer.openfeature);
```

{% /tab %}

{% tab title="Java" %}
Add the OpenFeature SDK and Datadog OpenFeature provider dependencies:

In the `build.gradle` file:

```groovy
dependencies {
    // OpenFeature SDK for flag evaluation
    implementation 'dev.openfeature:sdk:1.18.2'

    // Datadog OpenFeature Provider
    implementation 'com.datadoghq:dd-openfeature:1.57.0'
}
```

Enable the provider and start your application with the Java tracer:

```bash
# Required: Enable the feature flagging provider
# The EXPERIMENTAL_ prefix is historical; the provider is no longer experimental.
export DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true

# Optional: Enable flag evaluation metrics
export DD_METRICS_OTEL_ENABLED=true

java -javaagent:path/to/dd-java-agent.jar -jar your-application.jar
```

Register the Datadog OpenFeature provider:

```java
import dev.openfeature.sdk.OpenFeatureAPI;
import dev.openfeature.sdk.Client;
import datadog.trace.api.openfeature.Provider;

OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProviderAndWait(new Provider());
Client client = api.getClient("my-app");
```

{% /tab %}

{% tab title="Python" %}
Enable the provider with environment variables:

```bash
# Required: Enable the feature flags provider
export DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true

# Optional: Enable flag evaluation metrics
export DD_METRICS_OTEL_ENABLED=true
```

Install the Datadog Python SDK and OpenFeature SDK:

```bash
pip install ddtrace openfeature-sdk
```

Register the Datadog OpenFeature provider:

```python
from ddtrace import tracer
from openfeature import api
from ddtrace.openfeature import DataDogProvider

# Initialize the tracer (required for Remote Configuration)
tracer.configure()

# Create and register the Datadog provider
provider = DataDogProvider()
api.set_provider(provider)

# Create an OpenFeature client
client = api.get_client()
```

{% /tab %}

### Credentials at a glance{% #credentials-at-a-glance %}

| Credential     | Used by                                            | Where it goes                    | Sensitive?                              |
| -------------- | -------------------------------------------------- | -------------------------------- | --------------------------------------- |
| Client token   | Browser, mobile, and game SDKs                     | Client application configuration | No — safe to ship in public client code |
| Application ID | Browser and RUM-backed client SDKs                 | Client application configuration | No — public identifier                  |
| API key        | Datadog Agent for server-side Remote Configuration | Agent configuration only         | Yes — keep server-side only             |

Do not put API keys in browser, mobile, or game applications.

More information about OpenFeature SDK configuration options can be found in its [documentation](https://openfeature.dev/docs/reference/technologies/client/web/). For more information on creating client tokens and application IDs, see [API and Application Keys](https://docs.datadoghq.com/account_management/api-app-keys.md#client-tokens).

### Step 2: Create a feature flag{% #step-2-create-a-feature-flag %}

Go to [Create Feature Flag](https://app.datadoghq.com/feature-flags/create) in Datadog and configure the following:

- **Name and key**: The flag's display name and the key referenced in code
- **Variant type** and **variant values**: See [Variants and Flag Types](https://docs.datadoghq.com/feature_flags/concepts/variants_and_flag_types.md)
- **Distribution channels**: See [Distribution Channels](https://docs.datadoghq.com/feature_flags/concepts/distribution_channels.md)

{% alert level="warning" %}
Flag keys, variant keys, and variant values should be considered public when sent to client SDKs.
{% /alert %}

{% image
   source="https://docs.dd-static.net/images/getting_started/feature_flags/create-feature-flags.0de9433490db6b875434b55b554fbc38.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/getting_started/feature_flags/create-feature-flags.0de9433490db6b875434b55b554fbc38.png?auto=format&fit=max&w=850&dpr=2 2x"
   alt="Create Feature Flag" /%}

### Step 3: Evaluate the flag and write feature code{% #step-3-evaluate-the-flag-and-write-feature-code %}

In your application code, use the SDK to evaluate the flag and gate the new feature.

{% alert level="warning" %}
Datadog Feature Flags requires evaluation context attributes to be flat primitive values: strings, numbers, and Booleans. Do not pass nested objects or arrays; they are not supported and can cause exposure data to be dropped.
{% /alert %}

{% tab title="JavaScript browser" %}

```javascript
import { OpenFeature } from '@openfeature/web-sdk';

const client = OpenFeature.getClient();

// If applicable, set relevant attributes on the client's global context
// (e.g. org id, user email)
await OpenFeature.setContext({
    org_id: 2,
    user_id: 'user-123',
    email: 'user@example.com',
    targetingKey: 'user-123'
});

// This is what the SDK returns if the flag is disabled in
// the current environment
const fallback = false;

const showFeature = await client.getBooleanValue('show-new-feature', fallback);
if (showFeature) {
    // Feature code here
}
```

{% /tab %}

{% tab title="Node.js server" %}

```javascript
const evaluationContext = {
  targetingKey: req.session?.userID ?? 'unknown',
  companyID: req.session?.companyID
};

const isNewCheckoutEnabled = await client.getBooleanValue(
    'new-checkout-flow', // flag key
    false, // default value
    evaluationContext, // context
);

if (isNewCheckoutEnabled) {
    showNewCheckoutFlow();
} else {
    showLegacyCheckout();
}
```

{% /tab %}

{% tab title="Java" %}

```java
import dev.openfeature.sdk.EvaluationContext;
import dev.openfeature.sdk.MutableContext;

EvaluationContext context = new MutableContext("user-123")
    .add("email", "user@example.com")
    .add("tier", "premium");

boolean enabled = client.getBooleanValue("checkout.new", false, context);

if (enabled) {
    // New checkout flow
} else {
    // Old checkout flow
}
```

{% /tab %}

{% tab title="Python" %}

```python
from openfeature.evaluation_context import EvaluationContext

eval_ctx = EvaluationContext(
    targeting_key="user-123",
    attributes={
        "email": "user@example.com",
        "tier": "premium"
    }
)

enabled = client.get_boolean_value("new-checkout-flow", False, eval_ctx)

if enabled:
    show_new_checkout()
else:
    show_legacy_checkout()
```

{% /tab %}

After you've completed this step, redeploy the application to pick up these changes. Additional usage examples can be found in the platform-specific SDK pages linked above.

### Step 4: Define targeting rules and enable the feature flag{% #step-4-define-targeting-rules-and-enable-the-feature-flag %}

Configure [targeting rules](https://docs.datadoghq.com/feature_flags/concepts/targeting_rules.md) to define which subjects receive each variant. After saving your rules, enable the flag in your chosen environment.

{% alert level="info" %}
As a general best practice, roll out changes in a Staging environment before Production.
{% /alert %}

For percentage rollouts, see [Traffic Splitting and Randomization](https://docs.datadoghq.com/feature_flags/concepts/traffic_splitting.md).

### Step 5: Monitor your rollout{% #step-5-monitor-your-rollout %}

Monitor the feature rollout from the feature flag details page, which provides real-time exposure tracking and metrics such as error rate and page load time. As you incrementally release the feature with the flag, view the Real-Time Metric Overview panel in the Datadog UI to see how the feature impacts application performance.

{% image
   source="https://docs.dd-static.net/images/getting_started/feature_flags/real-time-flag-metrics.50ed4bef49eb143a1c21f740368cb39d.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/getting_started/feature_flags/real-time-flag-metrics.50ed4bef49eb143a1c21f740368cb39d.png?auto=format&fit=max&w=850&dpr=2 2x"
   alt="Real-time flag metrics panel" /%}

## Further reading{% #further-reading %}

- [Client-Side SDKs](https://docs.datadoghq.com/feature_flags/client.md)
- [Server-Side SDKs](https://docs.datadoghq.com/feature_flags/server.md)
- [Ship features faster and safer with Datadog Feature Flags](https://www.datadoghq.com/blog/feature-flags/)
- [How to bridge speed and quality in experiments through unified data](https://www.datadoghq.com/blog/experimental-data-datadog/)
- [How Datadog Feature Flags is resilient to cloud provider failures](https://www.datadoghq.com/blog/datadog-feature-flags-cloud-resilience/)
- [Make use of guardrail metrics and stop babysitting your releases](https://www.datadoghq.com/blog/guardrail-metrics)
