On this page

Experiment Node.js SDK

Official documentation for Amplitude Experiment's server-side Node.js SDK implementation.

This documentation has separate sections for remote and local evaluation:

Remote evaluation

Implements fetching variants for a user using remote evaluation.

Install

Node version compatibility

The Node Server SDK works with Node 10+.

bash
npm install --save @amplitude/experiment-node-server

Quick start

  1. Initialize the experiment client
  2. Fetch variants for the user
  3. Access a flag's variant
js
import { Experiment } from '@amplitude/experiment-node-server';

// (1) Initialize the experiment client
const experiment = Experiment.initializeRemote('<DEPLOYMENT_KEY>', {
    fetchTimeoutMillis: 500,
    fetchRetries: 1,
    fetchRetryBackoffMinMillis: 0,
    fetchRetryTimeoutMillis: 500,
});

// (2) Fetch variants for a user
const user = {
    user_id: 'user@company.com',
    device_id: 'abcdefg',
    user_properties: {
        'premium': true,
    },
};
const variants = experiment.fetchV2(user);

// (3) Access a flag's variant
const variant = variants['YOUR-FLAG-KEY'];
if (variant?.value === 'on') {
    // Flag is on
} else {
    // Flag is off
}

Initialize remote

Initialize the SDK client in your server on startup. The deployment key argument you pass to the apiKey parameter must live within the same project that you are sending analytics events to.

js
initializeRemote(apiKey: string, config?: RemoteEvaluationConfig): RemoteEvaluationClient
ParameterRequirementDescription
apiKeyrequiredThe deployment key that authorizes fetch requests and determines which flags to evaluate for the user.
configoptionalThe client configuration used to customize SDK client behavior.

Timeout and retry configuration

The default timeout and retry configuration options are too high for most server environments. Configure the timeout and retry options to best fit your performance requirements. If remote evaluation performance is too slow, consider using local evaluation.

js
import { Experiment } from '@amplitude/experiment-node-server';

const experiment = Experiment.initializeRemote('<DEPLOYMENT_KEY>', config: {
    fetchTimeoutMillis: 500,
    fetchRetries: 1,
    fetchRetryBackoffMinMillis: 0,
    fetchRetryTimeoutMillis: 500,
});

Configuration

Configure the SDK client during initialization.

EU data center

If you're using Amplitude's EU data center, configure the serverZone option on initialization.

NameDescriptionDefault Value
debugEnable additional debug logging.false
logLevelThe minimum log level to output. Options: Verbose, Debug, Info, Warn, Error, Disable. Go to custom logging.Error
loggerProviderCustom logger implementation. Implement the LoggerProvider interface to integrate with your logging solution. Go to custom logging.ConsoleLogger
serverZoneThe Amplitude data center to use. Either "us" or "eu""us"
serverUrlThe host to fetch variants from.https://api.lab.amplitude.com
fetchTimeoutMillisThe timeout for fetching variants in milliseconds. This timeout only applies to the initial request, not subsequent retries10000
fetchRetriesThe number of retries to attempt if a request to fetch variants fails.8
fetchRetryBackoffMinMillisThe minimum (initial) backoff after a request to fetch variants fails. The SDK scales this delay by the fetchRetryBackoffScalar500
fetchRetryBackoffMaxMillisThe maximum backoff between retries. If the scaled backoff becomes greater than the max, the SDK uses the max for all subsequent requests10000
fetchRetryBackoffScalarScales the minimum backoff exponentially.1.5
fetchRetryTimeoutMillisThe request timeout for retrying variant fetches.10000

Fetch

Fetches variants for a user and returns the results. The function remote evaluates the user for flags associated with the deployment used to initialize the SDK client.

js
fetchV2(user: ExperimentUser, fetchOptions?: FetchOptions): Promise<Variants>
ParameterRequirementDescription
userrequiredThe user for whom to fetch variants.
fetchOptionsoptionalThe options for the fetch request.

FetchOptions

NameDescriptionDefault Value
flagKeysSpecific flags or experiments to evaluate. If undefined, null, or empty, the SDK evaluates all flags and experiments.undefined
tracksExposureTo track or not track an exposure event for this fetch request. If undefined, uses the server's default behavior (doesn't track exposure).undefined
tracksAssignmentTo track or not track an assignment event for this fetch request. If undefined, uses the server's default behavior (does track assignment).undefined
js
const user = {
    user_id: 'user@company.com',
    device_id: 'abcdefg',
    user_properties: {
        'premium': true,
    },
};
const variants = await experiment.fetchV2(user);

After fetching variants for a user, you may to access the variant for a specific flag.

js
const variant = variants['YOUR-FLAG-KEY'];
if (variant?.value === 'on') {
    // Flag is on
} else {
    // Flag is off
}

Local evaluation

Implements evaluating variants for a user using local evaluation. If you plan to use local evaluation, understand the tradeoffs.

Install

Install the Node.js Server SDK with npm or yarn.

bash
npm install --save @amplitude/experiment-node-server

Quick start

  1. Initialize the local evaluation client.
  2. Start the local evaluation client.
  3. Evaluate a user.
js
import { Experiment } from '@amplitude/experiment-node-server';

// (1) Initialize the local evaluation client with a server deployment key.
const experiment = Experiment.initializeLocal('<DEPLOYMENT_KEY>', {
  // (Recommended) Enable local evaluation cohort targeting.
  cohortSyncConfig: {
    apiKey: '<API_KEY>',
    secretKey: '<SECRET_KEY>'
  }
});

// (2) Start the local evaluation client.
await experiment.start();

// (2) Evaluate a user.
const user = { device_id: 'abcdefg' };
const variants = experiment.evaluateV2(user);

Initialize Local

Initializes a local evaluation client.

Server deployment key

You must initialize the local evaluation client with a server deployment key to get access to local evaluation flag configs.

js
initializeLocal(apiKey: string, config?: LocalEvaluationConfig): LocalEvaluationClient
ParameterRequirementDescription
apiKeyrequiredThe server deployment key that authorizes fetch requests and determines which flags to evaluate for the user.
configoptionalThe client configuration used to customize SDK client behavior.

Flag streaming

Use the streamUpdates configuration to get flag config updates pushed to SDK (default false), instead of polling every flagConfigPollingIntervalMillis milliseconds. The time for SDK to receive the update after saving is generally less than one second. The SDK falls back to polling if streaming fails. Configure flagConfigPollingIntervalMillis configuration as well for fallback.

Configuration

You can configure the SDK client on initialization.

EU data center

If you're using Amplitude's EU data center, configure the serverZone option on initialization.

LocalEvaluationConfig

NameDescriptionDefault Value
debugSet to true to enable debug logging.false
logLevelThe minimum log level to output. Options: Verbose, Debug, Info, Warn, Error, Disable. Go to custom logging.Error
loggerProviderCustom logger implementation. Implement the LoggerProvider interface to integrate with your logging solution. Go to custom logging.ConsoleLogger
serverZoneThe Amplitude data center to use. Either "us" or "eu""us"
serverUrlThe host to fetch flag configurations from.https://api.lab.amplitude.com
bootstrapBootstrap the client with a map of flag key to flag configuration{}
flagConfigPollingIntervalMillisThe interval (in milliseconds) to poll for updated flag configs after calling start()30000
assignmentConfigDeprecated. Configuration for automatically tracking assignment events after an evaluation.null
exposureConfigConfiguration for tracking exposure events after an evaluation.null
streamUpdatesEnable streaming to replace polling for receiving flag config updates. Instead of polling every second, Amplitude servers push updates to SDK generally within a second. If the stream fails for any reason, the SDK falls back to polling automatically and retries streaming after some interval.false
streamServerUrlThe stream server url to stream from.https://stream.lab.amplitude.com
streamFlagConnTimeoutMillisThe timeout for establishing a valid flag config stream. This includes time for a connection to be established to stream server and time for receiving initial flag configs.1500
cohortSyncConfigConfiguration to enable cohort downloading for local evaluation cohort targeting.undefined

AssignmentConfig

NameDescriptionDefault Value
apiKeyThe analytics API key and NOT the experiment deployment keyrequired
cacheCapacityThe maximum number of assignments stored in the assignment cache65536
Analytics SDK OptionsOptions to configure the underlying Amplitude Analytics SDK used to track assignment events

ExposureConfig

NameDescriptionDefault Value
apiKeyThe analytics API key and NOT the experiment deployment keyrequired
cacheCapacityThe maximum number of exposures stored in the exposure cache65536
Analytics SDK OptionsOptions to configure the underlying Amplitude Analytics SDK used to track exposure events

CohortSyncConfig

NameDescriptionDefault Value
apiKeyThe analytics API key and NOT the experiment deployment keyrequired
secretKeyThe analytics secret keyrequired
maxCohortSizeThe maximum size of cohort that the SDK downloads. The SDK doesn't download cohorts larger than this size.2147483647
cohortPollingIntervalMillisThe interval, in milliseconds, to poll Amplitude for cohort updates (60000 minimum).60000
cohortServerUrlThe cohort server endpoint from which to fetch cohort data. For hitting the EU data center, set serverZone to eu. Setting this value overrides serverZone defaults.https://cohort-v2.lab.amplitude.com

Start

Start the local evaluation client, pre-fetching local evaluation mode flag configs for evaluation and starting the flag config poller at the configured interval.

js
start(): Promise<void>

You should await the result of start() to ensure that flag configs are ready to be used before calling evaluateV2()

js
await experiment.start();

Evaluate

Executes the evaluation logic using the flags pre-fetched on start(). You must give evaluate a user object argument. You can optionally pass an array of flag keys if you require only a specific subset of flag variants.

Exposure tracking

Set exposureConfig to enable exposure tracking. Then, set tracksExposure to true in EvaluateOptions when calling evaluateV2().

js
evaluateV2(user: ExperimentUser, flagKeys?: string[], options?: EvaluateOptions): Record<string, Variant>
ParameterRequirementDescription
userrequiredThe user to evaluate.
flagKeysoptionalSpecific flags or experiments to evaluate. If undefined, null, or empty, the SDK evaluates all flags and experiments.
optionsoptionalThe options for the evaluation request.
js
// The user to evaluate
const user = { device_id: 'abcdefg' };

// Evaluate all flag variants
const allVariants = experiment.evaluateV2(user);

// Evaluate a specific subset of flag variants
const specificVariants = experiment.evaluateV2(user, [
  'my-local-flag-1',
  'my-local-flag-2',
]);

EvaluateOptions

NameDescriptionDefault Value
tracksExposureIf true, the SDK tracks an exposure event for the evaluated variants.false

Local evaluation cohort targeting

Since version 1.13.4, the local evaluation SDK client supports downloading cohorts for local evaluation targeting. You must configure the cohortSyncConfig option with the analytics apiKey and secretKey on initialization to enable this support.

js
const experiment = Experiment.initializeLocal('<DEPLOYMENT_KEY>', {
  // (Recommended) Enable local evaluation cohort targeting.
  cohortSyncConfig: {
    apiKey: '<API_KEY>',
    secretKey: '<SECRET_KEY>'
  }
});

Consider configuring the maxCohortSize to avoid downloading large cohorts, which may cause your service to run out of memory. The SDK doesn't download cohorts that are too large.

Custom logging

Control log verbosity with the logLevel configuration, or implement the LoggerProvider interface to integrate your own logger.

Log levels

  • Verbose: Detailed debugging logs
  • Debug: Development and troubleshooting logs
  • Info: General information
  • Warn: Warnings
  • Error: Errors (default)
  • Disable: No logs

Custom logger

Implement the LoggerProvider interface to use your own logging solution:

ts
import { Experiment, LogLevel, LoggerProvider } from '@amplitude/experiment-node-server';

class MyCustomLogger implements LoggerProvider {
  verbose(message, ...optionalParams) {
    // Implement verbose logging
  }

  debug(message, ...optionalParams) {
    // Implement debug logging
  }

  info(message, ...optionalParams) {
    // Implement info logging
  }

  warn(message, ...optionalParams) {
    // Implement warn logging
  }

  error(message, ...optionalParams) {
    // Implement error logging
  }
}

// Initialize with custom logger
const experiment = Experiment.initializeLocal(
  '<DEPLOYMENT_KEY>',
  {
    logLevel: LogLevel.Debug,
    loggerProvider: new MyCustomLogger()
  }
);

Backward compatibility

The debug configuration field is still supported. When set to true, it overrides logLevel to Debug.

Access Amplitude cookies

If you use the Amplitude Analytics SDK on the client-side, the Node.js server SDK provides an AmplitudeCookie class with convenience functions for parsing and interacting with the Amplitude identity cookie. Use the class for server-side rendering (SSR) use cases where you need to:

  • Maintain consistent Device IDs between server-rendered and client-side code.
  • Access the user's Amplitude identity before the page renders.
  • Generate and set cookies on the server when they don't exist yet.

The class ensures that the Device ID on the server matches the Device ID set on the client, even if the client didn't generate a Device ID yet.

js
import { AmplitudeCookie } from '@amplitude/experiment-node-server';
import { v4 as uuidv4 } from 'uuid';
// Get the cookie name for the Amplitude API key
// For Browser SDK 2.0 cookies, pass true as second parameter:
// const ampCookieName = AmplitudeCookie.cookieName('amplitude-api-key', true);
const ampCookieName = AmplitudeCookie.cookieName('amplitude-api-key');
let deviceId = null;
// Try to get device ID from existing cookie
if (req.cookies[ampCookieName]) {
  deviceId = AmplitudeCookie.parse(req.cookies[ampCookieName]).device_id;
  // For Browser SDK 2.0: AmplitudeCookie.parse(req.cookies[ampCookieName], true).device_id;
}
// If no device ID found, generate a new one and set the cookie
if (!deviceId) {
  deviceId = uuidv4();
  const ampCookieValue = AmplitudeCookie.generate(deviceId);
  // For Browser SDK 2.0: AmplitudeCookie.generate(deviceId, true);
  res.cookie(ampCookieName, ampCookieValue, {
    domain: '.your-domain.com', // this should be the same domain used by the Amplitude JS SDK
    httpOnly: false,
    secure: false
  });
}

Was this helpful?