-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Documentation for dd-trace with feature flagging support #33165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
greghuels
merged 2 commits into
lr/server-sdk-overview-docs
from
greg.huels/feature-flags-nodejs
Dec 10, 2025
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,199 @@ | ||
| --- | ||
| title: Node.js Feature Flags Support | ||
| description: Set up Datadog Feature Flags for Node.js applications. | ||
| further_reading: | ||
| - link: "/feature_flags/setup/" | ||
| tag: "Documentation" | ||
| text: "Feature Flags Setup" | ||
| - link: "/apm/" | ||
| tag: "Documentation" | ||
| text: "APM Setup" | ||
| --- | ||
|
|
||
| ## Installing and initializing | ||
|
|
||
| Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install `dd-trace` and enable remote configuration with the `flaggingProvider` option as shown below. See documentation on `dd-trace` integration for detailed APM installation instructions. | ||
|
|
||
| ```shell | ||
| npm install dd-trace @openfeature/server-sdk | ||
| ``` | ||
|
|
||
| ```javascript | ||
| import { OpenFeature } from '@openfeature/server-sdk' | ||
| import tracer from 'dd-trace'; | ||
|
|
||
| tracer.init({ | ||
| experimental: { | ||
| flaggingProvider: { | ||
| enabled: true, | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| OpenFeature.setProvider(tracer.openfeature); | ||
| ``` | ||
|
|
||
| ### Accepting default variant until initialization is complete | ||
|
|
||
| When you call `setProvider` without waiting, the client returns default values until Remote Configuration loads in the background. This approach keeps your application responsive during startup but may serve defaults for early requests. | ||
|
|
||
| ```javascript | ||
| OpenFeature.setProvider(tracer.openfeature); | ||
| const client = OpenFeature.getClient(); | ||
|
|
||
| app.get('/my-endpoint', (req, res) => { | ||
| const value = client.getBooleanValue('my-flag', false); | ||
| if (value) { | ||
| res.send('feature enabled!'); | ||
| } else { | ||
| res.send('feature disabled!'); | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| ### Waiting for initialization before evaluating a flag | ||
|
|
||
| Use `setProviderAndWait` to ensure the provider fully initializes before evaluating flags. This guarantees that flag evaluations use actual configuration data rather than defaults, at the cost of delaying requests during initialization. | ||
|
|
||
| ```javascript | ||
| const initializationPromise = OpenFeature.setProviderAndWait(tracer.openfeature); | ||
| const client = OpenFeature.getClient(); | ||
|
|
||
| app.get('/my-endpoint', async (req, res) => { | ||
| await initializationPromise; | ||
|
|
||
| OpenFeature.setContext({ | ||
| userID: req.session?.userID, | ||
| companyID: req.session?.companyID | ||
| }); | ||
|
|
||
| const value = client.getBooleanValue('my-flag', false); | ||
| if (value) { | ||
| res.send('feature enabled!'); | ||
| } else { | ||
| res.send('feature disabled!'); | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| ## Set the evaluation context | ||
|
|
||
| Define who or what the flag evaluation applies to using an `EvaluationContext`. The evaluation context can include user or session information used to determine which flag variations should be returned. Call `OpenFeature.setContext` method before evaluating flags to ensure proper targeting. | ||
|
|
||
| ## Evaluating flags | ||
|
|
||
| After creating the `OpenFeature` client as described in the previous section, you can start reading flag values throughout your app. Flag evaluation uses locally cached data, so no network requests occur when evaluating flags. | ||
|
|
||
| Each flag is identified by a _key_ (a unique string) and can be evaluated with a _typed getter_ that returns a value of the expected type. If the flag doesn't exist or cannot be evaluated, the SDK returns the provided default value. | ||
|
|
||
| ### Boolean flags | ||
|
|
||
| Use `getBooleanValue()` for flags that represent on/off or true/false conditions. Optionally set the context for specific targeting rules. | ||
|
|
||
| ```javascript | ||
| OpenFeature.setContext({ | ||
| userID: req.session?.userID, | ||
| companyID: req.session?.companyID | ||
| }); | ||
|
|
||
| const isNewCheckoutEnabled = client.getBooleanValue( | ||
| 'new-checkout-flow', // flag key | ||
| false, // default value | ||
| ); | ||
|
|
||
| if (isNewCheckoutEnabled) { | ||
| showNewCheckoutFlow(); | ||
| } else { | ||
| showLegacyCheckout(); | ||
| } | ||
| ``` | ||
|
|
||
| ### String flags | ||
|
|
||
| Use `getStringValue()` for flags that select between multiple variants or configuration strings. For example: | ||
|
|
||
| ```javascript | ||
| OpenFeature.setContext({ | ||
| userID: req.session?.userID, | ||
| companyID: req.session?.companyID | ||
| }); | ||
|
|
||
| const theme = client.getStringValue( | ||
| 'ui-theme', // flag key | ||
| 'light', // default value | ||
| ); | ||
|
|
||
| switch (theme) { | ||
| case 'light': | ||
| setLightTheme(); | ||
| break; | ||
| case 'dark': | ||
| setDarkTheme(); | ||
| break; | ||
| case 'blue': | ||
| setBlueTheme(); | ||
| break; | ||
| default: | ||
| setLightTheme(); | ||
| } | ||
| ``` | ||
|
|
||
| ### Number flags | ||
|
|
||
| For number flags, use `getNumberValue()`. This is appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: | ||
|
|
||
| ```javascript | ||
| OpenFeature.setContext({ | ||
| userID: req.session?.userID, | ||
| companyID: req.session?.companyID | ||
| }); | ||
|
|
||
| const maxItems = client.getNumberValue( | ||
| 'max-cart-items', // flag key | ||
| 20, // default value | ||
| ); | ||
|
|
||
| const priceMultiplier = client.getNumberValue( | ||
| 'pricing-multiplier', // flag key | ||
| 1.3, // default value | ||
| ); | ||
| ``` | ||
|
|
||
| ### Object flags | ||
|
|
||
| For structured JSON data, use `getObjectValue()`. This method returns an `object`, which can represent primitives, arrays, or dictionaries. Object flags are useful for remote configuration scenarios where multiple properties need to be provided together. | ||
|
|
||
| ```javascript | ||
| OpenFeature.setContext({ | ||
| userID: req.session?.userID, | ||
| companyID: req.session?.companyID | ||
| }); | ||
|
|
||
| const defaultConfig = { | ||
| color: '#00A3FF', | ||
| fontSize: 14, | ||
| }; | ||
| const config = client.getObjectValue('ui-config', defaultConfig); | ||
| ``` | ||
|
|
||
| ### Flag evaluation details | ||
|
|
||
| When you need more than just the flag value, use the `get<Type>Details` functions. These methods return both the evaluated value and metadata explaining the evaluation: | ||
|
|
||
| * `getBooleanDetails() -> EvaluationDetails<boolean>` | ||
| * `getStringDetails() -> EvaluationDetails<string>` | ||
| * `getNumberDetails() -> EvaluationDetails<number>` | ||
| * `getObjectDetails() -> EvaluationDetails<JsonValue>` | ||
|
|
||
| For example: | ||
|
|
||
| ```javascript | ||
| const details = client.getStringDetails('paywall-layout', 'control'); | ||
|
|
||
| console.log(details.value); // Evaluated value (for example: "A", "B", or "control") | ||
| console.log(details.variant); // Variant name, if applicable | ||
| console.log(details.reason); // Description of why this value was chosen (for example: "TARGETING_MATCH") | ||
| console.log(details.errorCode); // The error that occurred during evaluation, if any | ||
| console.log(details.errorMessage); // A more detailed message of the error that occurred, if any | ||
| console.log(details.flagMetadata); // Additional information about the evaluation | ||
| ``` | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is also an env var they can use