Node.js SDK

Node.js, JavaScript/TypeScript client for Reflag.comarrow-up-right.

Reflag supports flag toggling, tracking flag usage, collecting feedback on features, and remotely configuring flags.

Installation

Install using your favorite package manager:

npm i @reflag/node-sdk

Other supported languages/frameworks are in the Supported languagesarrow-up-right documentation pages.

You can also use the HTTP API directlyarrow-up-right

Basic usage

To get started you need to obtain your secret key from the environment settingsarrow-up-right in Reflag.

triangle-exclamation

Reflag will load settings through the various environment variables automatically (see Configuring below).

  1. Find the Reflag secret key for your development environment under environment settingsarrow-up-right in Reflag.

  2. Set REFLAG_SECRET_KEY in your .env file

  3. Create a reflag.ts file containing the following:

import { ReflagClient } from "@reflag/node-sdk";

// Create a new instance of the client with the secret key. Additional options
// are available, such as supplying a logger and other custom properties.
//
// We recommend that only one global instance of `client` should be created
// to avoid multiple round-trips to our servers.
export const reflagClient = new ReflagClient();

// Initialize the client and begin fetching flag targeting definitions.
// You must call this method prior to any calls to `getFlags()`,
// otherwise an empty object will be returned.
reflagClient.initialize().then(() => {
  console.log("Reflag initialized!");
});

Once the client is initialized, you can obtain flags along with the isEnabled status to indicate whether the flag is targeted for this user/company:

circle-exclamation

You can also use the getFlags() method which returns a map of all flags:

High performance flag targeting

The SDK contacts the Reflag servers when you call initialize() and downloads the flags with their targeting rules. These rules are then matched against the user/company information you provide to getFlags() (or through bindClient(..).getFlags()). That means the getFlags() call does not need to contact the Reflag servers once initialize() has completed. ReflagClient will continue to periodically download the targeting rules from the Reflag servers in the background.

Batch Operations

The SDK automatically batches operations like user/company updates and flag tracking events to minimize API calls. The batch buffer is configurable through the client options:

You can manually flush the batch buffer at any time:

circle-check

Rate Limiting

The SDK includes automatic rate limiting for flag events to prevent overwhelming the API. Rate limiting is applied per unique combination of flag key and context. The rate limiter window size is configurable:

Flag definitions

Flag definitions include the rules needed to determine which flags should be enabled and which config values should be applied to any given user/company. Flag definitions are automatically fetched when calling initialize(). They are then cached and refreshed in the background. It's also possible to get the currently in use flag definitions:

Bootstrapping client-side applications

The getFlagsForBootstrap() method is designed for server-side rendering (SSR) scenarios where you need to pass flag data to client-side applications. This method returns raw flag data without wrapper functions, making it suitable for serialization and client-side hydration.

You can also use a bound client for simpler API:

Key differences from getFlags()

  • Raw data: Returns plain objects without track() functions, making them JSON serializable

  • Context included: Returns both the evaluated flags and the context used for evaluation

  • Bootstrapping focus: Designed specifically for passing data to client-side applications

Edge-runtimes like Cloudflare Workers

To use the Reflag NodeSDK with Cloudflare workers, set the node_compat flag in your wrangler filearrow-up-right.

Instead of using ReflagClient, use EdgeClient and make sure you call ctx.waitUntil(reflag.flush()); before returning from your worker function.

See examples/cloudflare-workerarrow-up-right for a deployable example.

Reflag maintains a cached set of flag definitions in the memory of your worker which it uses to decide which flags to turn on for which users/companies.

The SDK caches flag definitions in memory for fast performance. The first request to a new worker instance fetches definitions from Reflag's servers, while subsequent requests use the cache. When the cache expires, it's updated in the background. ctx.waitUntil(reflag.flush()) ensures completion of the background work, so response times are not affected. This background work may increase wall-clock time for your worker, but it will not measurably increase billable CPU time on platforms like Cloudflare.

Error Handling

The SDK is designed to fail gracefully and never throw exceptions to the caller. Instead, it logs errors and provides fallback behavior:

  1. Flag Evaluation Failures:

  2. Network Errors:

  3. Missing Context:

  4. Offline Mode:

The SDK logs all errors with appropriate severity levels. You can customize logging by providing your own logger:

Remote config

Remote config is a dynamic and flexible approach to configuring flag behavior outside of your app – without needing to re-deploy it.

Similar to isEnabled, each flag has a config property. This configuration is managed from within Reflag. It is managed similar to the way access to flags is managed, but instead of the binary isEnabled you can have multiple configuration values which are given to different user/companies.

key is mandatory for a config, but if a flag has no config or no config value was matched against the context, the key will be undefined. Make sure to check against this case when trying to use the configuration in your application. payload is an optional JSON value for arbitrary configuration needs.

Just as isEnabled, accessing config on the object returned by getFlags does not automatically generate a check event, contrary to the config property on the object returned by getFlag.

Configuring

The Reflag Node.js SDK can be configured through environment variables, a configuration file on disk or by passing options to the ReflagClient constructor. By default, the SDK searches for reflag.config.json in the current working directory.

Option
Type
Description
Env Var

secretKey

string

The secret key used for authentication with Reflag's servers.

REFLAG_SECRET_KEY

logLevel

string

The log level for the SDK (e.g., "DEBUG", "INFO", "WARN", "ERROR"). Default: INFO

REFLAG_LOG_LEVEL

offline

boolean

Operate in offline mode. Default: false, except in tests it will default to true based off of the TEST env. var.

REFLAG_OFFLINE

apiBaseUrl

string

The base API URL for the Reflag servers.

REFLAG_API_BASE_URL

flagOverrides

Record<string, boolean>

An object specifying flag overrides for testing or local development. See examples/express/app.test.tsarrow-up-right for how to use flagOverrides in tests.

REFLAG_FLAGS_ENABLED, REFLAG_FLAGS_DISABLED

configFile

string

Load this config file from disk. Default: reflag.config.json

REFLAG_CONFIG_FILE

reflag.config.json example:

When using a reflag.config.json for local development, make sure you add it to your .gitignore file. You can also set these options directly in the ReflagClient constructor. The precedence for configuration options is as follows, listed in the order of importance:

  1. Options passed along to the constructor directly,

  2. Environment variable,

  3. The config file.

Type safe flags

To get type checked flags, install the Reflag CLI:

then generate the types:

This will generate a reflag.d.ts containing all your flags. Any flag look ups will now be checked against the flags that exist in Reflag.

Here's an example of a failed type check:

Type check failed

This is an example of a failed config payload check:

Config type check failed

Testing

When writing tests that cover code with flags, you can toggle flags on/off programmatically to test the different behavior.

reflag.ts:

app.test.ts:

See more on flag overrides in the section below.

Flag Overrides

Flag overrides allow you to override flags and their configurations locally. This is particularly useful for development and testing. You can specify overrides in three ways:

  1. Through environment variables:

  1. Through reflag.config.json:

  1. Programmatically through the client options:

You can use a simple Record<string, boolean> and pass it either in the constructor or by setting client.flagOverrides:

To get dynamic overrides, use a function which takes a context and returns a boolean or an object with the shape of {isEnabled, config}:

Remote Flag Evaluation

In addition to local flag evaluation, Reflag supports remote evaluation using stored context. This is useful when you want to evaluate flags using user/company attributes that were previously sent to Reflag:

Remote evaluation is particularly useful when:

  • You want to use the most up-to-date user/company attributes stored in Reflag

  • You don't want to pass all context attributes with every evaluation

  • You need to ensure consistent flag evaluation across different services

Using with Express

A popular way to integrate the Reflag Node.js SDK is through an express middleware.

See examples/express/app.tsarrow-up-right for a full example.

Remote flag evaluation with stored context

If you don't want to provide context each time when evaluating flags but rather you would like to utilize the attributes you sent to Reflag previously (by calling updateCompany and updateUser) you can do so by calling getFlagsRemote (or getFlagRemote for a specific flag) with providing just userId and companyId. These methods will call Reflag's servers and flags will be evaluated remotely using the stored attributes.

circle-exclamation

Opting out of tracking

There are use cases in which you not want to be sending user, company and track events to Reflag.comarrow-up-right. These are usually cases where you could be impersonating another user in the system and do not want to interfere with the data being collected by Reflag.

To disable tracking, bind the client using bindClient() as follows:

Another way way to disable tracking without employing a bound client is to call getFlag() or getFlags() by supplying enableTracking: false in the arguments passed to these functions.

circle-exclamation

Flushing

ReflagClient employs a batching technique to minimize the number of calls that are sent to Reflag's servers.

By default, the SDK automatically subscribes to process exit signals and attempts to flush any pending events. This behavior is controlled by the flushOnExit option in the client configuration:

Tracking custom events and setting custom attributes

Tracking allows events and updating user/company attributes in Reflag. For example, if a customer changes their plan, you'll want Reflag to know about it, in order to continue to provide up-do-date targeting information in the Reflag interface.

The following example shows how to register a new user, associate it with a company and finally update the plan they are on.

It's also possible to achieve the same through a bound client in the following manner:

Some attributes are used by Reflag to improve the UI, and are recommended to provide for easier navigation:

  • name -- display name for user/company,

  • email -- the email of the user,

  • avatar -- the URL for user/company avatar image.

Attributes cannot be nested (multiple levels) and must be either strings, integers or booleans.

Managing Last seen

By default updateUser/updateCompany calls automatically update the given user/company Last seen property on Reflag servers.

You can control if Last seen should be updated when the events are sent by setting meta.active = false. This is often useful if you have a background job that goes through a set of companies just to update their attributes but not their activity.

Example:

bindClient() updates attributes on the Reflag servers but does not automatically update Last seen.

Zero PII

The Reflag SDK doesn't collect any metadata and HTTP IP addresses are not being stored. For tracking individual users, we recommend using something like database ID as userId, as it's unique and doesn't include any PII (personal identifiable information). If, however, you're using e.g. email address as userId, but prefer not to send any PII to Reflag, you can hash the sensitive data before sending it to Reflag:

Migrating from Bucket SDK

If you have been using the Bucket SDKs previously, the following list will help you migrate to Reflag SDK:

  • Bucket* classes, and types have been renamed to Reflag* (e.g. BucketClient is now ReflagClient)

  • Feature* classes, and types have been renamed to Flag* (e.g. Feature is now Flag, RawFeatures is now RawFlags)

  • When using strongly-typed flags, the new Flags interface replaced Features interface

  • All methods that contained feature in the name have been renamed to use the flag terminology (e.g. getFeature is getFlag)

  • All environment variables that were prefixed with BUCKET_ are now prefixed with REFLAG_

  • The BUCKET_HOST environment variable and host option have been removed from ReflagClient constructor, use REFLAG_API_BASE_URL instead

  • The BUCKET_FEATURES_ENABLED and BUCKET_FEATURES_DISABLED have been renamed to REFLAG_FLAGS_ENABLED and REFLAG_FLAGS_DISABLED

  • The default configuration file has been renamed from bucketConfig.json to reflag.config.json

  • The fallbackFeatures property in client constructor and configuration files has been renamed to fallbackFlags

  • featureKey has been renamed to flagKey in all methods that accepts that argument

  • The SDKs will not emit evaluate and evaluate-config events anymore

Typescript

Types are bundled together with the library and exposed automatically when importing through a package manager.

License

MIT License Copyright (c) 2025 Bucket ApS

Last updated

Was this helpful?