Migrating from Statsig to LaunchDarkly Experimentation

This guide explains how to migrate your Statsig experiment implementation to LaunchDarkly’s Experimentation feature. It focuses on experiments and metrics, covering the conceptual differences between the two platforms and showing side-by-side SDK code comparisons for Node.js (server-side) and JavaScript.

This guide covers the following SDKs:

The steps in this guide include:

  1. Implementing LaunchDarkly SDKs
  2. Recreating flags in LaunchDarkly
  3. Migrating Statsig metrics to LaunchDarkly metrics
  4. Creating experiments in LaunchDarkly

This guide focuses on information specific to migrating from Statsig. For a general overview of what to consider when migrating to LaunchDarkly, read Migrating your existing feature flag solution to LaunchDarkly.

How LaunchDarkly experiments differ from Statsig experiments

The most important conceptual difference is that LaunchDarkly experiments are built on top of feature flags. In Statsig, an experiment is a standalone entity you query directly with getExperiment(). In LaunchDarkly, you create a feature flag whose variations represent your experiment arms, then create an experiment on top of that flag in the LaunchDarkly UI. Your SDK code evaluates the flag, and LaunchDarkly records the assignment automatically.

This means a LaunchDarkly experiment flag works like any other flag in your codebase. You call variation(), or a typed variant like stringVariation() or jsonVariation(), and the SDK handles assignment, bucketing, and exposure tracking for you.

Mapping terms between LaunchDarkly and Statsig

StatsigLaunchDarklyNotes
ExperimentExperimentLaunchDarkly experiments are flag-based
Experiment parameterFlag variationEach arm of the experiment is a flag variation
Feature gateBoolean feature flagTwo variations of true or false
Dynamic configMultivariate feature flagCan use number, string, or JSON variations
LayerExperiment layerUsed in mutually exclusive experiments
StatsigUserLDContextRefer to User and context mapping
userIDLDContext.keyThe context key. Together, kind and key uniquely identify a LaunchDarkly context.
custom attributesTop-level context attributesLaunchDarkly does not nest custom attributes
customIDsMulti-context (kind: ‘multi’)To learn more, read Multi-contexts
logEvent()track()Used to record metric events
Server Secret KeySDK keyServer-side only. Do not expose in code.
Client SDK KeyClient-side IDSafe to expose in browser code
Console metricMetricSeveral metric types available

Migration strategy

We recommend running Statsig and LaunchDarkly in parallel during your migration rather than switching over all at once. This lets you validate that bucketing and results are consistent before fully cutting over.

We suggest this approach:

  1. Set up LaunchDarkly: Create your experiment flags and metrics in LaunchDarkly.
  2. Evaluate both SDKs: In your application, call both Statsig.getExperiment() and client.variation(). Log both results temporarily to verify consistent assignments.
  3. Track in both systems: Call both Statsig.logEvent() and client.track() so metric data accumulates in LaunchDarkly while you validate.
  4. Cut over: When you’re confident the LaunchDarkly experiment is running correctly, remove the Statsig SDK calls and shut down the Statsig client.

Step 1: Implement LaunchDarkly SDKs

LaunchDarkly offers over 25 server-side and client-side SDKs. To begin, decide on which LaunchDarkly SDKs you want to use.

The following sections give examples of how to install, initialize, and shut down two LaunchDarkly SDKs. For a full understanding of how to implement an SDK, select an SDK from the list and read its reference topic.

Installation

To begin, replace your Statsig SDK dependency with the appropriate LaunchDarkly SDK. Here are examples for Node.js (server-side) and JavaScript:

$# Remove
$npm uninstall statsig-node
$
$# Add
$npm install @launchdarkly/node-server-sdk

Initialization

Next, initialize your SDK. Here’s a comparison of how the Node.js (server-side) and JavaScript SDKs are initialized in Statsig and LaunchDarkly:

1// Statsig
2import Statsig from 'statsig-node';
3
4await Statsig.initialize('server-secret-key', {
5 environment: { tier: 'staging' },
6});
7
8// LaunchDarkly
9import * as ld from '@launchdarkly/node-server-sdk';
10
11const client = ld.init('sdk-key');
12await client.waitForInitialization();

The sdk-key or client-side-id credential corresponds to a specific environment. For example, “production” or “staging.” Select the correct credential from your environment’s SDK keys page.

Shutdown

Here’s a comparison of how to shut down the Node.js (server-side) and the JavaScript SDKs in Statsig and LaunchDarkly:

Shutting down
1//Statsig
2await Statsig.shutdown();
3
4//LaunchDarkly
5await client.close();

User and context mapping

LaunchDarkly contexts are data objects that represent users, devices, organizations, and other entities. LaunchDarkly represents contexts using an LDContext object where Statsig uses a StatsigUser.

The main differences are:

StatsigLaunchDarkly
userIDkey.
User object has no context kind

Include kind, typically ‘user’.

First-class fields include userID, email, ip, and userAgent. Other attributes live under custom.

Custom attributes are top-level on LDContext, not nested under custom. Map Statsig custom fields to top-level attributes.

Example user object
1//Statsig
2const user = {
3 userID: 'user-123',
4 email: 'user@example.com',
5 custom: {
6 country: 'US',
7 plan: 'enterprise',
8 company_id: 'acme-corp',
9 },
10};
11
12//LaunchDarkly
13const context: ld.LDContext = {
14 kind: 'user',
15 key: 'user-123',
16 email: 'user@example.com',
17 country: 'US',
18 plan: 'enterprise',
19 company_id: 'acme-corp',
20};

Multi-contexts

Statsig’s customIDs field lets you associate a user with other entities, such as a company or device, for bucketing purposes. LaunchDarkly handles this with multi-contexts, where each entity is a separate context kind within a single kind: 'multi' object.

Here is a comparison of Statsig and LaunchDarkly multi-entity objects:

Multi-context
1//Statsig
2const user = {
3 userID: 'user-123',
4 email: 'user@example.com',
5 customIDs: {
6 companyID: 'acme-corp',
7 },
8};
9
10//LaunchDarkly
11const context: ld.LDContext = {
12 kind: 'multi',
13 user: {
14 kind: 'user',
15 key: 'user-123',
16 email: 'user@example.com',
17 },
18 company: {
19 kind: 'company',
20 key: 'acme-corp',
21 },
22};

You can then target or bucket your experiment by either the user or company context kind in the LaunchDarkly UI.

Step 2: Recreate flags in LaunchDarkly

To move gates and configs from Statsig, recreate them as LaunchDarkly flags. You can use one of three methods:

  • create flags in the LaunchDarkly UI
  • use the LaunchDarkly REST API
  • use an infrastructure as code method such as Terraform

Statsig concepts map to LaunchDarkly flags this way:

StatsigLaunchDarkly

Feature gates (boolean checks)

Boolean flags
Dynamic configs

Multivariate flags (for scalar values) or JSON flags when the payload is structured JSON.

Treat experiments separately. There is no import path that recreates a Statsig experiment as a LaunchDarkly experiment. Instead, create a LaunchDarkly flag whose variations match your arms, then attach an experiment to that flag in the UI, as described in Setting up experiments in LaunchDarkly.

Before recreating large sets of flags, audit your existing Statsig gates and configs for anything stale or no longer in use. Where possible, reuse the same flag keys in LaunchDarkly. LaunchDarkly keys may contain only letters, numbers, periods (.), underscores (_), and dashes (-). We recommend you rename them only when Statsig keys use other characters.

Statsig often models environments with targeting tiers or metadata on one object. LaunchDarkly gives each environment its own targeting for the same flag, and each environment uses SDK credentials. Create flags once per LaunchDarkly project, then configure each environment in the LaunchDarkly UI (or API) to match how Statsig behaved in dev, staging, and production.

To learn more, read Creating flags.

Evaluating experiment variations

In Statsig, you call getExperiment() and then call .get() on the result to retrieve individual parameters. In LaunchDarkly, you call variation() directly on the client to get the variation value for the flag that backs the experiment.

LaunchDarkly offers two approaches for experiments with multiple parameters.

Option 1: String or boolean flag for a single parameter

Use a typed variation method when your experiment controls a single value.

1//Statsig
2const experiment = Statsig.getExperiment(user, 'cta_color_experiment');
3const ctaColor = experiment.get('cta_color', 'blue');
4
5// LaunchDarkly
6const ctaColor = client.stringVariation('cta-color-experiment', context, 'blue');

Option 2: JSON flag for multiple parameters

Use a JSON flag when your experiment controls multiple parameters at once. Each variation is a JSON object containing all the parameters for that arm.

For example, the variations for a checkout experiment might be:

  • Control: { "cta_text": "Buy Now", "cta_color": "blue" }
  • Treatment: { "cta_text": "Get Started", "cta_color": "green" }

Here’s how:

1// Statsig
2const experiment = Statsig.getExperiment(user, 'checkout_flow_experiment');
3const ctaText = experiment.get('cta_text', 'Buy Now');
4const ctaColor = experiment.get('cta_color', 'blue');
5
6interface CheckoutConfig {
7 cta_text: string;
8 cta_color: string;
9}
10
11// LaunchDarkly
12const defaults: CheckoutConfig = { cta_text: 'Buy Now', cta_color: 'blue' };
13
14const config = client.jsonVariation(
15 'checkout-flow-experiment',
16 context,
17 defaults
18) as CheckoutConfig;
19
20const { cta_text: ctaText, cta_color: ctaColor } = config;

Step 3: Migrate Statsig metrics to LaunchDarkly metrics

LaunchDarkly supports both LaunchDarkly-hosted metrics and warehouse native metrics:

  • LaunchDarkly-hosted metrics: LaunchDarkly-hosted metrics are created from metric events that you instrument in your application code.
  • Warehouse native metrics: If you are using BigQuery, Databricks, Redshift, or Snowflake to store metric events, you can export experiment data to your warehouse where you can conduct custom, advanced analysis in addition to LaunchDarkly’s existing experiment analysis. To learn how to set up warehouse native metrics, read Warehouse native metrics.

The following sections describe the process for migrating Statsig metrics to LaunchDarkly-hosted metrics.

Statsig metrics are created from logEvent() calls. LaunchDarkly-hosted metrics are created from metric events that you instrument in your app using track() calls in LaunchDarkly SDKs. Each event uses a unique event key, which is the same string you pass as the first argument to track(). To learn more, read Sending custom events.

Tracking metric events

Statsig uses logEvent() to record metric events. LaunchDarkly-hosted metrics use track(). Both associate the event with the user or context that triggered it.

Here is a comparison of the two methods:

1//Statsig
2Statsig.logEvent(user, 'purchase_completed', purchaseAmount, {
3 product_id: 'prod-123',
4 category: 'electronics',
5});
6
7// LaunchDarkly
8client.track('purchase-completed', {
9 product_id: 'prod-123',
10 category: 'electronics'
11 },
12 purchaseAmount);
Metric values and metadata

In the Node.js (server-side) SDK, track() uses the signature track(key, context, data?, metricValue?). Pass Statsig’s numeric value as metricValue (the fourth argument). Use undefined for data when you are not attaching a JSON payload to the event. LaunchDarkly does not support arbitrary metadata on individual track() calls the way Statsig’s fourth metadata argument does. If you need to segment results by a property such as product_id, include that attribute on the LDContext you pass to track() instead.

Step 4: Set up experiments in LaunchDarkly

After updating your SDK and importing your flags and metrics, you can create your experiment in the LaunchDarkly UI. The process differs from Statsig’s because LD experiments are flag-based.

To set up an experiment in LaunchDarkly:

  1. Create or choose a feature flag with variations representing your experiment arms. For a JSON experiment, each variation is a JSON object of parameters. For a simpler A/B test, each variation is a string or boolean value.
  2. In the LaunchDarkly UI, navigate to Experiments and click Create experiment.
  3. Select the flag you created as the experiment flag.
  4. Choose the flag variation to use as the control.
  5. Add one or more metrics for the events you want to measure in the experiment.
  6. Set a traffic allocation and start the experiment.

That’s it! You’ve migrated your experiments from Statsig to LaunchDarkly.

To learn more, read Creating experiments.

Next steps

That’s just the beginning of everything you can do with LaunchDarkly. Here are some suggestions for further reading:

Or, if you want to learn more about the SDKs we used as examples above:

If you have more questions or need further assistance, start a Support ticket.

Want to know more? Start a trial.
Your 14-day trial begins as soon as you sign up. Get started in minutes using the in-app Quickstart. You'll discover how easy it is to release, monitor, and optimize your software.

Want to try it out? Start a trial.