> ## Documentation Index
> Fetch the complete documentation index at: https://launchdarkly.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK 3.x to 4.0 migration guide

This topic explains the changes in the JavaScript SDK 4.0 release and how to adapt code that uses a 3.x version of the [JavaScript SDK](/docs/sdk/client-side/javascript) to use version 4.0 or later.

**Version 4.0 includes several breaking changes**. Before you migrate to version 4.0, update to the latest 3.x version. If you update to the latest 3.x version, deprecation warnings appear in areas of your code that need to be changed for 4.0. You can update them at your own pace while still using 3.x, rather than migrating everything simultaneously. To learn more about updating to the latest 3.x version, visit the [SDK's GitHub repository](https://github.com/launchdarkly/js-client-sdk).

## Package name and location changes

In v4.0 of the SDK, the node module is now named `@launchdarkly/js-client-sdk`. To begin the migration, install the new package and swap all references from `launchdarkly-js-client-sdk` to `@launchdarkly/js-client-sdk`.

## Client initialization

In v4.0 of the SDK, client initialization has changed in the following ways:

* The `initialize` method was removed.
* Initialization is now split into two parts: `createClient` and `start`.
* `LDOptions`,  which was formerly passed into the `initialize()` function, is now split into two types: `LDStartOptions` and `LDOptions`. To learn more, read [Changes to LDOptions](#changes-to-ldoptions).

This two-step process ensures that you can register all event listeners and perform any necessary setup before the client begins connecting to LaunchDarkly. This eliminates race conditions where events might be missed if listeners were registered after the client had already started initializing.

Here is the new client initialization method:

<CodeGroup>
  ```js title="JavaScript SDK v4.0" lines wrap theme={null}
    import { createClient } from '@launchdarkly/js-client-sdk';

    // Create client
    const client = createClient('example-client-side-id', context, options);

    // Then start the client
    client.start();
  ```

  ```js title="JavaScript SDK v3.x" lines wrap theme={null}
    import LDClient from 'launchdarkly-js-client-sdk';

    const client = LDClient.initialize('example-client-side-id', context, options);
  ```

  ```ts title="JavaScript SDK v3.x (TypeScript)" lines wrap theme={null}
  import * as LDClient from 'launchdarkly-js-client-sdk';

  const client = LDClient.initialize('example-client-side-id', context, options);
  ```
</CodeGroup>

### Client initialization flow

In v4.0 of the SDK, client initialization flow has changed in the following ways:

* In v4.0 the `waitForInitialization()` method returns a result object instead of rejecting promises. The v3.x `waitUntilReady()` method has been removed.
* `waitForInitialization()` now always resolves, never rejects, and returns a result object with a `status` field.
* `timeout` is now specified as an option object, `{ timeout: 5 }`, instead of a direct parameter
* The result object allows you to handle all cases, including success, failure, and timeout, without try/catch.

Here is the new client initialization flow:

<CodeGroup>
  ```js title="JavaScript SDK v4.0" expandable lines wrap theme={null}
    // Recommended: Using waitForInitialization (always resolves with status)
    const result = await client.waitForInitialization({ timeout: 5 });

    if (result.status === 'complete') {
    // Client initialized successfully
    } else if (result.status === 'failed') {
    // Client failed to initialize
    console.error('Initialization failed:', result.error);
    } else if (result.status === 'timeout') {
    // Initialization timed out
    console.error('Initialization timed out');
    }

    // Note: Events still work if you prefer that approach
    client.on('ready', () => {
    // Client is ready (success or failure)
    });
    client.on('initialized', () => {
    // Client initialized successfully
    });
    client.on('failed', (err) => {
    // Client failed to initialize
    });
  ```

  ```js title="JavaScript SDK v3.x" expandable lines wrap theme={null}
    // Option 1: Using waitUntilReady (never rejects)
    await client.waitUntilReady();

    // Option 2: Using waitForInitialization (rejects on failure)
    try {
    await client.waitForInitialization(5);
    } catch (err) {
    // Failure - but this could be an unhandled rejection if not caught
    }

    // Option 3: Using event listeners
    client.on('ready', () => {
    // Client is ready (success or failure)
    });
    client.on('initialized', () => {
    // Client initialized successfully
    });
    client.on('failed', (err) => {
    // Client failed to initialize
    });
  ```
</CodeGroup>

## Changes to LDOptions

In v4.0 of the SDK, `LDOptions` has changed in the following ways:

* The `bootstrap` option moved from `LDOptions` to `LDStartOptions` and `identify`. Bootstrapping data is now part of the initialization of a client instance. `identify` is a key part of the client initialization process required to associate the instance with an initial context.
* The SDK now defaults to using local storage-based caching. Previously, to enable local storage caching, you needed to set this as a special value for the `bootstrap` property.
* Version 3.x of the SDK used the `streamUrl`, `baseUrl`, and `eventsUrl` properties to specify the base URIs for alternative service endpoints. Version 4.0 of the JavaScript SDK uses the `streamUri`, `baseUri`, and `eventsUri` properties to specify the base URIs for alternative service endpoints.

To learn more, read the following SDK documentation:

* [LDOptions](https://launchdarkly.github.io/js-core/packages/sdk/browser/docs/interfaces/LDOptions.html)
* [LDStartOptions](https://launchdarkly.github.io/js-core/packages/sdk/browser/docs/interfaces/LDStartOptions.html)
* [LDIdentifyOptions](https://launchdarkly.github.io/js-core/packages/sdk/browser/docs/interfaces/LDIdentifyOptions.html)

### Report changes

In the JavaScript SDK v3.x and earlier, if you used `REPORT`, enabled the `useReport` configuration option, and wanted to use streaming, then you had to use use the LaunchDarkly EventSource polyfill.

The JavaScript SDK v4.0 supports `REPORT` directly. If you enable the [`useReport` configuration option](https://launchdarkly.github.io/js-core/packages/sdk/browser/docs/interfaces/LDOptions.html#useReport), no polyfill or additional configuration is required.

## Flag evaluation now has typed methods

The `variation` method lets you evaluate a feature flag. The `variationDetail` method lets you evaluate a feature flag while providing more information about how the value was calculated.

In v4.0 of the SDK, you can also use typed methods. These methods include:

* `boolVariationDetail` for boolean flags.
* `numberVariationDetail` for number flags.
* `stringVariationDetail` for string flags.
* `jsonVariationDetail` for JSON flags.

To learn more about the `*variationDetail` methods, read [`LDEvaluationDetail`](https://launchdarkly.github.io/js-core/packages/sdk/browser/docs/types/LDEvaluationDetail.html). To learn more about the configuration option, read [`evaluationReasons`](https://launchdarkly.github.io/js-core/packages/sdk/browser/docs/interfaces/LDOptions.html#evaluationReasons).

## Events changes

Version 4.0 of the SDK includes changes to the `allFlags()` method and the `sendEvents` configuration.

### Analytics events changes

In v4.0 of the SDK, the `allFlags()` method no longer sends [analytics events](/docs/sdk/concepts/events). To learn more, read [Getting all flags](/docs/sdk/features/all-flags#javascript).

### Changes to sending events

In v4.x of the JavaScript SDK, you can disable sending events by [setting the `sendEvents` configuration](https://launchdarkly.github.io/js-core/packages/sdk/browser/docs/interfaces/LDOptions.html#sendEvents) to `false`.

<View title="Developer">Earlier versions of the JavaScript SDK respect the [Do Not Track events](https://www.eff.org/issues/do-not-track) header. If an end user has Do Not Track enabled in their browser, earlier versions do not send analytics events for flag evaluations or metrics to `events.launchdarkly.com`.</View>

<View title="Federal docs">Earlier versions of the JavaScript SDK respect the [Do Not Track events](https://www.eff.org/issues/do-not-track) header. If an end user has Do Not Track enabled in their browser, earlier versions do not send analytics events for flag evaluations or metrics to `events.launchdarkly.us`.</View>

<View title="EU docs">Earlier versions of the JavaScript SDK respect the [Do Not Track events](https://www.eff.org/issues/do-not-track) header. If an end user has Do Not Track enabled in their browser, earlier versions do not send analytics events for flag evaluations or metrics to `events.eu.launchdarkly.com`.</View>

## Flag listener changes

In v4.0 of the SDK, flag listeners have changed in the following ways:

* The `change` event listener now receives `(context, changedKeys)`, where `changedKeys` is an array of strings. The SDK no longer returns the flag value object along with this event.
* The event does not include flag values. You must call `variation()` to get the current value.
* `change:<example-flag-key>` event listener now only receives `(context)`.

Here is the new flag listener method:

<CodeGroup>
  ```js title="JavaScript SDK v4.0" expandable lines wrap theme={null}
  // General change event - fires when any flags change
  client.on('change', (context, changedKeys) => {
    // context: The LDContext for which flags changed
    // changedKeys: Array of flag keys that changed

    // Still need to call variation() to get current values
    changedKeys.forEach(flagKey => {
      const flagValue = client.variation(flagKey, defaultValue);
    });
  });

  // Specific flag change event - fires when a specific flag changes
  client.on('change:example-flag-key', (context) => {
    // Only fires when 'my-flag' changes
    const flagValue = client.variation('example-flag-key', false);
  });
  ```

  ```js title="JavaScript SDK v3.x" lines wrap theme={null}
  // The exact signature may have varied, but typically:
    client.on('change', (changedFlags) => {
    // changedFlags is a key value pair where the flag key is mapped
    // to a diff object.
  });
  ```
</CodeGroup>

## Error event handling changes

The new SDK has changed how errors are logged when error event listeners are present.

In v3.x of the SDK, the `maybeReportError` function would check if there was an error listener:

* If an error listener was registered, the error event was emitted but **not logged** to the console
* If no error listener was registered, the error was logged to the console

This meant that if you wanted to handle errors yourself, you wouldn't get duplicate error logs.

In v4.0 of the SDK, the client always registers a default error listener that logs errors via the logger. This means:

* Errors are **always logged** using the logger, even if you have your own error listeners
* Your error listeners will still receive the error events
* You may see duplicate error logs if you're also logging errors in your error handler

The new error handling process allows for more robust control over what errors are ignored. This avoids not logging or informing end users when an unhandled error happens. Our recommendation is to implement `LDLogger` for your client to suppress handled errors.

## Addition of data sources

Version 4.0 of the SDK adds the `change`, `error`, and `dataSourceStatus` methods to subscribe to events. When you subscribe to `dataSourceStatus` events, the state returned may be one of `Initializing`, `Valid`, `Interrupted`, `SetOffline`, `Closed`.

To learn more, read [Monitoring SDK status](/docs/sdk/features/monitoring#javascript).

## Understanding what was deprecated

All types and methods that were marked as deprecated in the last 3.x release have been removed from the 4.0 release. If you were using a recent 3.x version, you should already have received compile-time deprecation warnings with suggestions for their recommended replacements.

For a full list of deprecated types and methods, read the [release notes in GitHub](https://github.com/launchdarkly/js-client-sdk/releases).
