> ## 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.

# Data saving mode

<View title="Developer" />

<View title="Federal docs" />

<View title="EU docs" />

<Note>
  **Data saving mode is available for Early Access**

  Data saving mode is supported in the SDKs listed below. It is also supported in the [Relay Proxy](/docs/sdk/relay-proxy).

  Data saving mode is only available to members of LaunchDarkly's Early Access Program (EAP). If you want access to this feature, [join the EAP](mailto:product@launchdarkly.com).
</Note>

This topic explains how data saving mode works in the LaunchDarkly SDKs that support it, listed below. The [Relay Proxy](/docs/sdk/relay-proxy) also supports data saving mode.

Server-side SDKs in data saving mode first open a polling connection to LaunchDarkly. The initial payload from this connection contains the data the SDK will need to operate and perform flag evaluations.

Subsequently, server-side SDKs in data saving mode open a streaming connection and receive realtime flag configuration changes over the stream. These configuration changes include only the difference between the server-side SDK's stored configuration and the latest configuration in LaunchDarkly. The SDKs use in-memory data for the unchanged aspects of the flag configuration.

The SDKs fall back to using a polling connection if LaunchDarkly streaming is unavailable. Data saving mode includes additional configuration options that let you set a backup data source, enabling automatic failover if a connection is unavailable.

Depending on the number of flags in your project and the complexity of their configuration, data saving mode can significantly improve performance, including reducing your network costs when in polling mode or on reconnection. Additionally, SDKs in data saving mode have reduced memory and CPU usage overall.

<Tip>
  **Track service connection usage by application**

  When using data saving mode, you can track which applications are consuming service connections by configuring application metadata. Set the `applicationId` in your SDK configuration to see a per-application breakdown on the **Service connections** usage page under the **SDK App ID** dimension. Server-side streaming connections without `applicationId` configured appear as "Unknown." To learn how, read [Application metadata configuration](/docs/sdk/features/app-config).
</Tip>

## Server-side SDKs

This feature is available in the following SDKs:

* [.NET (server-side)](#net-server-side)
* [C++ (server-side)](#c++-server-side)
* [Go](#go)
* [Java](#java)
* [Node.js (server-side)](#node-js-server-side)
* [Python](#python)
* [Ruby](#ruby)
* [Rust](#rust)

<Note>
  **File initializers provide startup data but do not initialize the SDK**

  When you configure a custom data source, a file initializer provides an initial set of flag data so your application can begin evaluating flags at startup. However, the SDK itself does not reach an initialized state from using the file initializer alone. The SDK is fully initialized only after it uses a streaming or polling synchronizer to connect to LaunchDarkly and obtain a complete set of flag data.

  The examples in this topic all pair a file initializer with a synchronizer. If you configure a file initializer without a synchronizer, your flags still load and evaluate correctly, but the SDK does not report itself as initialized. In this case, evaluate flags directly without gating your application's startup on the SDK initialization status. As a best practice, we recommend not blocking application startup on SDK initialization in any configuration, so your application can start in a degraded but functional state and rely on fallback values until the SDK is ready.

  A file initializer reads the same file format as the file-based data source, including the `flags` and `flagValues` formats. To learn about the file format, read [Reading flags from a file](/docs/sdk/features/flags-from-files).
</Note>

### .NET (server-side)

<Accordion title="Expand .NET (server-side) SDK code sample">
  To enable data saving mode:

  1. If you are using the [Relay Proxy](/docs/sdk/relay-proxy), upgrade your Relay Proxy to version 9.0.0-rc.1 or later.
  2. Upgrade your .NET (server-side) SDK to version 8.11 or later.
  3. Update your SDK configuration to enable the `DataSystem` configuration option.

  Here's how to enable the `DataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```csharp title=".NET (server-side) SDK v8.11+" lines wrap theme={null}
    using LaunchDarkly.Sdk.Server;

    var config = Configuration.Builder("YOUR_SDK_KEY")
        .DataSystem(Components.DataSystem().Default())
        .Build();

    var client = new LdClient(config);
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. It uses a combination of streaming and polling to initialize the SDK, provide real time updates, and switch between streaming and polling automatically to provide redundancy.

  #### Relay proxy with LaunchDarkly API fallback

  <CodeGroup>
    ```csharp title=".NET (server-side) SDK v8.11+" expandable lines wrap theme={null}
    using LaunchDarkly.Sdk.Server;
    using LaunchDarkly.Sdk.Server.Integrations;

    var relayUri = new Uri("http://my-relay-proxy:8030");
    var relayEndpoints = Components.ServiceEndpoints().RelayProxy(relayUri);

    var config = Configuration.Builder("YOUR_SDK_KEY")
        .DataSystem(
            Components.DataSystem().Custom()
                .Synchronizers(
                    DataSystemComponents.Streaming()
                        .ServiceEndpointsOverride(relayEndpoints),
                    DataSystemComponents.Streaming(),
                    DataSystemComponents.Polling()
                )
        )
        .Build();

    var client = new LdClient(config);
    ```
  </CodeGroup>

  #### File-based bootstrap with live updates

  <Note>
    **File-based bootstrap works in regulated or connectivity-restricted environments**

    File-based bootstrap works in production for organizations with compliance-driven restrictions on outbound connections to LaunchDarkly servers.

    If you use a file initializer in production, you must keep the file in sync with flag changes you make in the LaunchDarkly UI. LaunchDarkly does not update it for you.
  </Note>

  <CodeGroup>
    ```csharp title=".NET (server-side) SDK v8.11+" expandable lines wrap theme={null}
    using LaunchDarkly.Sdk.Server;
    using LaunchDarkly.Sdk.Server.Integrations;

    var config = Configuration.Builder("YOUR_SDK_KEY")
        .DataSystem(
            Components.DataSystem().Custom()
                .Initializers(
                    FileData.DataSource().FilePaths("flags.json"),
                    DataSystemComponents.Polling()
                )
                .Synchronizers(
                    DataSystemComponents.Streaming(),
                    DataSystemComponents.Polling()
                )
        )
        .Build();

    var client = new LdClient(config);
    ```
  </CodeGroup>

  To learn more, read [`DataSystemModes`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.Server.Integrations.DataSystemModes.html) for information about pre-configured data system modes, and [`DataSystemBuilder`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.Server.Integrations.DataSystemBuilder.html) for information on additional configuration options.
</Accordion>

### C++ (server-side)

<Accordion title="Expand C++ (server-side) SDK code sample">
  To enable data saving mode:

  1. If you are using the [Relay Proxy](/docs/sdk/relay-proxy), upgrade your Relay Proxy to version 9.0.0-rc.1 or later.
  2. Upgrade your C++ (server-side) SDK to version 3.12 or later.
  3. Update your SDK configuration to enable the `DataSystem` configuration option.

  The C++ SDK provides both a native C++ API and a C binding. The following examples show each.

  Here's how to enable the `DataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```cpp title="C++ (server-side) SDK v3.12+ (native)" lines wrap theme={null}
    using FDv2 = server_side::config::builders::DataSystemBuilder::FDv2;

    auto config_builder = server_side::ConfigBuilder("YOUR_SDK_KEY");
    config_builder.DataSystem().Method(FDv2::Default());

    auto config = config_builder.Build();
    if (!config) {
        /* an error occurred, config is not valid */
    }
    ```

    ```c title="C++ (server-side) SDK v3.12+ (C binding)" lines wrap theme={null}
    LDServerConfigBuilder builder = LDServerConfigBuilder_New("YOUR_SDK_KEY");

    LDServerFDv2Builder fdv2 = LDServerFDv2Builder_Default();
    LDServerConfigBuilder_DataSystem_FDv2(builder, fdv2);

    LDServerConfig config;
    LDStatus status = LDServerConfigBuilder_Build(builder, &config);

    if (!LDStatus_Ok(status)) {
        /* an error occurred, config is not valid */
    }
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. It uses a combination of streaming and polling to initialize the SDK, provide real time updates, and switch between streaming and polling automatically to provide redundancy.

  #### Relay Proxy with LaunchDarkly API fallback

  <CodeGroup>
    ```cpp title="C++ (server-side) SDK v3.12+ (native)" lines wrap theme={null}
    using FDv2 = server_side::config::builders::DataSystemBuilder::FDv2;

    std::string relay_url = "http://my-relay-proxy:8030";

    auto config_builder = server_side::ConfigBuilder("YOUR_SDK_KEY");
    config_builder.DataSystem().Method(
        FDv2::Custom()
            .Initializer(FDv2::Polling().BaseUrl(relay_url))
            .Initializer(FDv2::Polling())
            .Synchronizer(FDv2::Streaming().BaseUrl(relay_url))
            .Synchronizer(FDv2::Streaming())
            .Synchronizer(FDv2::Polling()));

    auto config = config_builder.Build();
    if (!config) {
        /* an error occurred, config is not valid */
    }
    ```

    ```c title="C++ (server-side) SDK v3.12+ (C binding)" lines wrap theme={null}
    const char* relay_url = "http://my-relay-proxy:8030";

    LDServerFDv2PollingBuilder initializer_relay = LDServerFDv2PollingBuilder_New();
    LDServerFDv2PollingBuilder_BaseURL(initializer_relay, relay_url);
    LDServerFDv2PollingBuilder initializer_ld = LDServerFDv2PollingBuilder_New();

    LDServerFDv2StreamingBuilder synchronizer_relay = LDServerFDv2StreamingBuilder_New();
    LDServerFDv2StreamingBuilder_BaseURL(synchronizer_relay, relay_url);
    LDServerFDv2StreamingBuilder synchronizer_ld = LDServerFDv2StreamingBuilder_New();
    LDServerFDv2PollingBuilder synchronizer_poll = LDServerFDv2PollingBuilder_New();

    LDServerFDv2Builder fdv2 = LDServerFDv2Builder_Custom();
    LDServerFDv2Builder_Initializer_Polling(fdv2, initializer_relay);
    LDServerFDv2Builder_Initializer_Polling(fdv2, initializer_ld);
    LDServerFDv2Builder_Synchronizer_Streaming(fdv2, synchronizer_relay);
    LDServerFDv2Builder_Synchronizer_Streaming(fdv2, synchronizer_ld);
    LDServerFDv2Builder_Synchronizer_Polling(fdv2, synchronizer_poll);

    LDServerConfigBuilder builder = LDServerConfigBuilder_New("YOUR_SDK_KEY");
    LDServerConfigBuilder_DataSystem_FDv2(builder, fdv2);

    LDServerConfig config;
    LDStatus status = LDServerConfigBuilder_Build(builder, &config);

    if (!LDStatus_Ok(status)) {
        /* an error occurred, config is not valid */
    }
    ```
  </CodeGroup>

  To learn more, read [`DataSystemBuilder`](https://launchdarkly.github.io/cpp-sdks/libs/server-sdk/docs/html/classlaunchdarkly_1_1server__side_1_1config_1_1builders_1_1DataSystemBuilder.html) for information on additional configuration options.
</Accordion>

### Go

<Accordion title="Expand Go SDK code sample">
  To enable data saving mode:

  1. If you are using the [Relay Proxy](/docs/sdk/relay-proxy), upgrade your Relay Proxy to version 9.0.0-rc.1 or later.
  2. Upgrade your Go SDK to version 7.11 or later.
  3. Update your SDK configuration to enable the `DataSystem` configuration option.

  Here's how to enable the `DataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```go title="Go SDK v7.11+" lines wrap theme={null}
    import (
        "github.com/launchdarkly/go-sdk-common/v3/ldcontext"
        ld "github.com/launchdarkly/go-server-sdk/v7"
        "github.com/launchdarkly/go-server-sdk/v7/ldcomponents"
    )

    var config ld.Config

    config.DataSystem = ldcomponents.DataSystem().Default()

    client, _ := ld.MakeCustomClient("YOUR_SDK_KEY", config, 5*time.Second)
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. It uses a combination of streaming and polling to initialize the SDK, provide real time updates, and switch between streaming and polling automatically to provide redundancy.

  #### Relay proxy with LaunchDarkly API fallback

  <CodeGroup>
    ```go title="Go SDK v7.11+" expandable lines wrap theme={null}
    import (
        ld "github.com/launchdarkly/go-server-sdk/v7"
        "github.com/launchdarkly/go-server-sdk/v7/ldcomponents"
    )

    var config ld.Config

    relayURI := "http://my-relay-proxy:8030"

    config.DataSystem = ldcomponents.DataSystem().Custom().
        Synchronizers(
            ldcomponents.StreamingDataSourceV2().BaseURI(relayURI),
            ldcomponents.StreamingDataSourceV2(),
            ldcomponents.PollingDataSourceV2(),
        )

    client, _ := ld.MakeCustomClient("YOUR_SDK_KEY", config, 5*time.Second)
    ```
  </CodeGroup>

  #### File-based bootstrap with live updates

  <Note>
    **File-based bootstrap works in regulated or connectivity-restricted environments**

    File-based bootstrap works in production for organizations with compliance-driven restrictions on outbound connections to LaunchDarkly servers.

    If you use a file initializer in production, you must keep the file in sync with flag changes you make in the LaunchDarkly UI. LaunchDarkly does not update it for you.
  </Note>

  <CodeGroup>
    ```go title="Go SDK v7.11+" expandable lines wrap theme={null}
    import (
        ld "github.com/launchdarkly/go-server-sdk/v7"
        "github.com/launchdarkly/go-server-sdk/v7/ldcomponents"
        "github.com/launchdarkly/go-server-sdk/v7/ldfiledatav2"
    )

    var config ld.Config

    config.DataSystem = ldcomponents.DataSystem().Custom().
        Initializers(
            ldfiledatav2.DataSource().FilePaths("flags.json").AsInitializer(),
            ldcomponents.PollingDataSourceV2().AsInitializer(),
        ).
        Synchronizers(
            ldcomponents.StreamingDataSourceV2(),
            ldcomponents.PollingDataSourceV2(),
        )

    client, _ := ld.MakeCustomClient("YOUR_SDK_KEY", config, 5*time.Second)
    ```
  </CodeGroup>

  To learn more, read [`DataSystem`](https://pkg.go.dev/github.com/launchdarkly/go-server-sdk/v7#Config.DataSystem). For information on additional configuration options, read [`DataSystemConfiguration`](https://pkg.go.dev/github.com/launchdarkly/go-server-sdk/v7@v7.11.0/subsystems#DataSystemConfiguration).
</Accordion>

### Java

<Accordion title="Expand Java SDK code sample">
  To enable data saving mode:

  1. If you are using the [Relay Proxy](/docs/sdk/relay-proxy), upgrade your Relay Proxy to version 9.0.0-rc.1 or later.
  2. Upgrade your Java (server-side) SDK to version 7.11 or later.
  3. Update your SDK configuration to enable the `dataSystem` configuration option.

  Here's how to enable the `dataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```java title="Java SDK v7.11+" lines wrap theme={null}
    import com.launchdarkly.sdk.server.*;

    LDConfig config = new LDConfig.Builder()
        .dataSystem(Components.dataSystem().defaultMode())
        .build();

    LDClient client = new LDClient("YOUR_SDK_KEY", config);
    ```
  </CodeGroup>

  We recommend the default data system configuration for most customers. It uses a combination of streaming and polling to initialize the SDK, provide real time updates, and switch between streaming and polling automatically to provide redundancy.

  #### Relay proxy with LaunchDarkly API fallback

  <CodeGroup>
    ```java title="Java SDK v7.11+" expandable lines wrap theme={null}
    import com.launchdarkly.sdk.server.*;
    import com.launchdarkly.sdk.server.integrations.*;

    import java.net.URI;

    URI relayUri = URI.create("http://my-relay-proxy:8030");
    ServiceEndpointsBuilder relayEndpoints = Components.serviceEndpoints().relayProxy(relayUri);

    LDConfig config = new LDConfig.Builder()
        .dataSystem(
            Components.dataSystem().custom()
                .synchronizers(
                    DataSystemComponents.streamingSynchronizer()
                        .serviceEndpointsOverride(relayEndpoints),
                    DataSystemComponents.streamingSynchronizer(),
                    DataSystemComponents.pollingSynchronizer()
                )
        )
        .build();

    LDClient client = new LDClient("YOUR_SDK_KEY", config);
    ```
  </CodeGroup>

  #### File-based bootstrap with live updates

  <Note>
    **File-based bootstrap works in regulated or connectivity-restricted environments**

    File-based bootstrap works in production for organizations with compliance-driven restrictions on outbound connections to LaunchDarkly servers.

    If you use a file initializer in production, you must keep the file in sync with flag changes you make in the LaunchDarkly UI. LaunchDarkly does not update it for you.
  </Note>

  <CodeGroup>
    ```java title="Java SDK v7.11+" expandable lines wrap theme={null}
    import com.launchdarkly.sdk.server.*;
    import com.launchdarkly.sdk.server.integrations.*;

    LDConfig config = new LDConfig.Builder()
        .dataSystem(
            Components.dataSystem().custom()
                .initializers(
                    FileData.initializer().filePaths("flags.json"),
                    DataSystemComponents.pollingInitializer()
                )
                .synchronizers(
                    DataSystemComponents.streamingSynchronizer(),
                    DataSystemComponents.pollingSynchronizer()
                )
        )
        .build();

    LDClient client = new LDClient("YOUR_SDK_KEY", config);
    ```
  </CodeGroup>

  To learn more, read [`DataSystemModes`](https://launchdarkly.github.io/java-core/lib/sdk/server/com/launchdarkly/sdk/server/integrations/DataSystemModes.html)for information about pre-configured data system modes, and [`DataSystemBuilder`](https://launchdarkly.github.io/java-core/lib/sdk/server/com/launchdarkly/sdk/server/integrations/DataSystemBuilder.html) for information on additional configuration options.
</Accordion>

### Node.js (server-side)

<Accordion title="Expand Node.js (server-side) code sample">
  To enable data saving mode:

  1. If you are using the [Relay Proxy](/docs/sdk/relay-proxy), upgrade your Relay Proxy to version 9.0.0-rc.1 or later.
  2. Upgrade your Node.js (server-side) SDK to version 9.10 or later.
  3. Update your SDK configuration:
     * Enable the `dataSystem` configuration option.
     * Migrate existing `LDOptions` fields. The following existing options were previously top-level `LDOptions` fields and are part of the `dataSystem` configuration as of version 9.10: `persistentStore`, `stream`, `streamInitialReconnectDelay`, `pollInterval`, `useLDD`.

  Here's how to enable the `dataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```js title="Node.js (server-side) SDK v9.10+" lines wrap theme={null}
    const ldClient = LaunchDarkly.init('YOUR_SDK_KEY', {
      dataSystem: {
        dataSource: {
            dataSourceOptionsType: 'standard',

            // if you use the stream, streamInitialReconnectDelay, or pollInterval options,
            // these options are now part of the dataSystem options,
            // and are set within the dataSource option
        }
        // if you use the persistentStore or useLDD option,
        // these options are now part of the dataSystem option
      }
    });
    ```
  </CodeGroup>

  We recommend the `standard` data source option for most customers. It uses a combination of streaming and polling to initialize the SDK, provide real time updates, and switch between streaming and polling automatically to provide redundancy.

  #### File-based bootstrap with live updates

  <Note>
    **File-based bootstrap works in regulated or connectivity-restricted environments**

    File-based bootstrap works in production for organizations with compliance-driven restrictions on outbound connections to LaunchDarkly servers.

    If you use a file initializer in production, you must keep the file in sync with flag changes you make in the LaunchDarkly UI. LaunchDarkly does not update it for you.
  </Note>

  <CodeGroup>
    ```js title="Node.js (server-side) SDK v9.10+" lines wrap theme={null}
    const ldClient = LaunchDarkly.init('YOUR_SDK_KEY', {
      dataSystem: {
        dataSource: {
          dataSourceOptionsType: 'custom',
          initializers: [
            { type: 'file', paths: ['flags.json'] },
            { type: 'polling' },
          ],
          synchronizers: [
            { type: 'streaming' },
            { type: 'polling' },
          ],
        }
      }
    });
    ```
  </CodeGroup>

  To learn more, read [`dataSystem`](https://launchdarkly.github.io/js-core/packages/sdk/server-node/docs/interfaces/LDOptions.html#dataSystem). For information on additional configuration options, read [`LDDataSystemOptions`](https://launchdarkly.github.io/js-core/packages/sdk/server-node/docs/interfaces/LDDataSystemOptions.html).
</Accordion>

### Python

<Accordion title="Expand Python SDK code sample">
  To enable data saving mode:

  1. If you are using the [Relay Proxy](/docs/sdk/relay-proxy), upgrade your Relay Proxy to version 9.0.0-rc.1 or later.
  2. Upgrade your Python SDK to version 9.13 or later.
  3. Update your SDK configuration to enable the `DataSystem` configuration option.

  Here's how to enable the `DataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```python title="Python SDK v9.13+" lines wrap theme={null}
    import ldclient
    from ldclient.config import Config
    from ldclient import datasystem

    ldclient.set_config(
        Config(
            "YOUR_SDK_KEY",
            datasystem_config=datasystem.default().build(),
        )
    )

    client = ldclient.get()
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. It uses a combination of streaming and polling to initialize the SDK, provide real time updates, and switch between streaming and polling automatically to provide redundancy.

  #### Relay proxy with LaunchDarkly API fallback

  <CodeGroup>
    ```python title="Python SDK v9.13+" expandable lines wrap theme={null}
    import ldclient
    from ldclient.config import Config
    from ldclient import datasystem

    relay_uri = "http://my-relay-proxy:8030"

    ldclient.set_config(
        Config(
            "YOUR_SDK_KEY",
            datasystem_config=datasystem.custom()
                .synchronizers(
                    datasystem.streaming_ds_builder().base_uri(relay_uri),
                    datasystem.streaming_ds_builder(),
                    datasystem.polling_ds_builder(),
                )
                .build(),
        )
    )

    client = ldclient.get()
    ```
  </CodeGroup>

  #### File-based bootstrap with live updates

  <Note>
    **File-based bootstrap works in regulated or connectivity-restricted environments**

    File-based bootstrap works in production for organizations with compliance-driven restrictions on outbound connections to LaunchDarkly servers.

    If you use a file initializer in production, you must keep the file in sync with flag changes you make in the LaunchDarkly UI. LaunchDarkly does not update it for you.
  </Note>

  <CodeGroup>
    ```python title="Python SDK v9.13+" expandable lines wrap theme={null}
    import ldclient
    from ldclient.config import Config
    from ldclient import datasystem

    ldclient.set_config(
        Config(
            "YOUR_SDK_KEY",
            datasystem_config=datasystem.custom()
                .initializers([
                    datasystem.file_ds_builder(paths=["flags.json"]),
                    datasystem.polling_ds_builder(),
                ])
                .synchronizers(
                    datasystem.streaming_ds_builder(),
                    datasystem.polling_ds_builder(),
                )
                .build(),
        )
    )

    client = ldclient.get()
    ```
  </CodeGroup>

  To learn more, read [`ldclient.datasystem`](https://launchdarkly-python-sdk.readthedocs.io/en/latest/api-main.html#module-ldclient.datasystem). For information on additional configuration options, read [`DataSystemConfig`](https://launchdarkly-python-sdk.readthedocs.io/en/latest/api-main.html#ldclient.config.DataSystemConfig).
</Accordion>

### Ruby

<Accordion title="Expand Ruby SDK code sample">
  To enable data saving mode:

  1. If you are using the [Relay Proxy](/docs/sdk/relay-proxy), upgrade your Relay Proxy to version 9.0.0-rc.1 or later.
  2. Upgrade your Ruby SDK to version 8.12.0 or later.
  3. Update your SDK configuration to enable the `data_system_config` configuration option.

  Here's how to enable the `data_system_config` configuration option:

  #### Standard setup

  <CodeGroup>
    ```ruby title="Ruby SDK v8.12.0+" lines wrap theme={null}
    require 'ldclient-rb'

    config = LaunchDarkly::Config.new(
      data_system_config: LaunchDarkly::DataSystem.default.build
    )

    client = LaunchDarkly::LDClient.new("YOUR_SDK_KEY", config)
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. It uses a combination of streaming and polling to initialize the SDK, provide real time updates, and switch between streaming and polling automatically to provide redundancy.

  #### Relay proxy with LaunchDarkly API fallback

  <CodeGroup>
    ```ruby title="Ruby SDK v8.12.0+" lines wrap theme={null}
    require 'ldclient-rb'

    relay_uri = "http://my-relay-proxy:8030"

    config = LaunchDarkly::Config.new(
      data_system_config: LaunchDarkly::DataSystem.custom
        .synchronizers([
          LaunchDarkly::DataSystem.streaming_ds_builder.base_uri(relay_uri),
          LaunchDarkly::DataSystem.streaming_ds_builder,
          LaunchDarkly::DataSystem.polling_ds_builder,
        ])
        .build
    )

    client = LaunchDarkly::LDClient.new("YOUR_SDK_KEY", config)
    ```
  </CodeGroup>

  #### File-based bootstrap with live updates

  <Note>
    **File-based bootstrap works in regulated or connectivity-restricted environments**

    File-based bootstrap works in production for organizations with compliance-driven restrictions on outbound connections to LaunchDarkly servers.

    If you use a file initializer in production, you must keep the file in sync with flag changes you make in the LaunchDarkly UI. LaunchDarkly does not update it for you.
  </Note>

  <CodeGroup>
    ```ruby title="Ruby SDK v8.12.0+" expandable lines wrap theme={null}
    require 'ldclient-rb'

    config = LaunchDarkly::Config.new(
      data_system_config: LaunchDarkly::DataSystem.custom
        .initializers([
          LaunchDarkly::Integrations::FileData.data_source_v2(paths: ['flags.json']),
          LaunchDarkly::DataSystem.polling_ds_builder,
        ])
        .synchronizers([
          LaunchDarkly::DataSystem.streaming_ds_builder,
          LaunchDarkly::DataSystem.polling_ds_builder,
        ])
        .build
    )

    client = LaunchDarkly::LDClient.new("YOUR_SDK_KEY", config)
    ```
  </CodeGroup>

  To learn more, read [`LaunchDarkly::DataSystem`](https://launchdarkly.github.io/ruby-server-sdk/LaunchDarkly/DataSystem.html). To learn more about additional configuration options, read [`DataSystem::ConfigBuilder`](https://launchdarkly.github.io/ruby-server-sdk/LaunchDarkly/DataSystem/ConfigBuilder.html).
</Accordion>

### Rust

<Accordion title="Expand Rust SDK code sample">
  To enable data saving mode:

  1. If you are using the [Relay Proxy](/docs/sdk/relay-proxy), upgrade your Relay Proxy to version 9.0.0-rc.1 or later.
  2. Upgrade your Rust SDK to version 3.3 or later.
  3. Update your SDK configuration to enable the `data_system` configuration option.

  Here's how to enable the `data_system` configuration option:

  #### Standard setup

  <CodeGroup>
    ```rust title="Rust SDK v3.3+" lines wrap theme={null}
    use launchdarkly_server_sdk::{Client, ConfigBuilder, DataSystemBuilder};

    let config = ConfigBuilder::new("YOUR_SDK_KEY")
        .data_system(&DataSystemBuilder::default())
        .build()
        .unwrap();

    let client = Client::build(config).unwrap();
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. It uses a combination of streaming and polling to initialize the SDK, provide real time updates, and switch between streaming and polling automatically to provide redundancy.

  #### Relay Proxy with LaunchDarkly API fallback

  <CodeGroup>
    ```rust title="Rust SDK v3.3+" lines wrap theme={null}
    use launchdarkly_server_sdk::{
        Client, ConfigBuilder, DataSystemBuilder, FDv2PollingBuilder, FDv2StreamingBuilder,
    };
    use launchdarkly_sdk_transport::HyperTransport;

    let relay_url = "http://my-relay-proxy:8030";

    let mut relay_initializer = FDv2PollingBuilder::<HyperTransport>::new();
    relay_initializer.base_url(relay_url);

    let mut relay_synchronizer = FDv2StreamingBuilder::<HyperTransport>::new();
    relay_synchronizer.base_url(relay_url);

    let mut data_system = DataSystemBuilder::custom();
    data_system
        .initializer(relay_initializer)
        .initializer(FDv2PollingBuilder::<HyperTransport>::new())
        .synchronizer(relay_synchronizer)
        .synchronizer(FDv2StreamingBuilder::<HyperTransport>::new())
        .synchronizer(FDv2PollingBuilder::<HyperTransport>::new());

    let config = ConfigBuilder::new("YOUR_SDK_KEY")
        .data_system(&data_system)
        .build()
        .unwrap();

    let client = Client::build(config).unwrap();
    ```
  </CodeGroup>

  To learn more, read [`DataSystemBuilder`](https://docs.rs/launchdarkly-server-sdk/latest/launchdarkly_server_sdk/struct.DataSystemBuilder.html) for information on additional configuration options.
</Accordion>

## Client-side SDKs

Client-side SDKs in data saving mode use the same data system pipeline as server-side SDKs, adapted to the lifecycle and connectivity characteristics of the client environment. SDKs may switch between connection modes automatically in response to application lifecycle events and network state changes. Some client-side SDKs use streaming when the application is active or in the foreground for real-time flag updates, and switch to polling or reduce activity when the application is backgrounded or hidden.

This feature is available in the following SDKs:

* [Android](#android)
* [Flutter](#flutter)
* [JavaScript](#javascript)
* [React Native](#react-native)
* [React Web](#react-web)
* [Vue](#vue): The Vue SDK relies on the JavaScript SDK for this functionality.

### Android

<Accordion title="Expand Android SDK code sample">
  <Warning>
    **Consider mobile update tails before shipping EAP code**

    Mobile applications have long update tails. Apps you ship today may remain installed on end-user devices for years. If you include the EAP version of the Android Client SDK in a production release, the EAP-era API surface and behaviors may persist in deployed apps long after data saving mode graduates to General Availability. Make sure your release timeline can tolerate shipping a non-stable API.
  </Warning>

  To enable data saving mode:

  1. Upgrade your Android Client SDK to version 5.13 or later.
  2. Request to [join the Early Access Program](mailto:product@launchdarkly.com). Wait to receive confirmation from LaunchDarkly that data saving mode is enabled for your account.
  3. Update your SDK configuration to enable the `dataSystem` configuration option.

  Here's how to enable the `dataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```kotlin title="Android Client SDK v5.13+ (Kotlin)" lines wrap theme={null}
    val config = LDConfig.Builder(AutoEnvAttributes.Enabled)
        .mobileKey("example-mobile-key")
        .dataSystem(Components.dataSystem())
        .build()
    ```

    ```java title="Android Client SDK v5.13+ (Java)" lines wrap theme={null}
    LDConfig config = new LDConfig.Builder(AutoEnvAttributes.Enabled)
        .mobileKey("example-mobile-key")
        .dataSystem(Components.dataSystem())
        .build();
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. It uses a combination of streaming and polling to initialize the SDK, provide real time updates, and switch between streaming and polling automatically to provide redundancy.

  #### Automatic mode switching

  The Android Client SDK switches between connection modes automatically based on app lifecycle and network connectivity. You can disable automatic switching entirely, or selectively disable lifecycle-driven or network-driven switching.

  To disable automatic switching entirely and keep the SDK in a single connection mode regardless of lifecycle or network changes:

  <CodeGroup>
    ```kotlin title="Android Client SDK v5.13+ (Kotlin)" lines wrap theme={null}
    val config = LDConfig.Builder(AutoEnvAttributes.Enabled)
        .mobileKey("example-mobile-key")
        .dataSystem(
            Components.dataSystem()
                .automaticModeSwitching(AutomaticModeSwitchingConfig.disabled())
                .foregroundConnectionMode(ConnectionMode.STREAMING))
        .build()
    ```

    ```java title="Android Client SDK v5.13+ (Java)" lines wrap theme={null}
    LDConfig config = new LDConfig.Builder(AutoEnvAttributes.Enabled)
        .mobileKey("example-mobile-key")
        .dataSystem(
            Components.dataSystem()
                .automaticModeSwitching(AutomaticModeSwitchingConfig.disabled())
                .foregroundConnectionMode(ConnectionMode.STREAMING))
        .build();
    ```
  </CodeGroup>

  To disable lifecycle-driven switching but continue switching modes when network connectivity changes:

  <CodeGroup>
    ```kotlin title="Android Client SDK v5.13+ (Kotlin)" lines wrap theme={null}
    val config = LDConfig.Builder(AutoEnvAttributes.Enabled)
        .mobileKey("example-mobile-key")
        .dataSystem(
            Components.dataSystem()
                .automaticModeSwitching(
                    DataSystemComponents.automaticModeSwitching()
                        .lifecycle(false)
                        .network(true)
                        .build()))
        .build()
    ```

    ```java title="Android Client SDK v5.13+ (Java)" lines wrap theme={null}
    LDConfig config = new LDConfig.Builder(AutoEnvAttributes.Enabled)
        .mobileKey("example-mobile-key")
        .dataSystem(
            Components.dataSystem()
                .automaticModeSwitching(
                    DataSystemComponents.automaticModeSwitching()
                        .lifecycle(false)
                        .network(true)
                        .build()))
        .build();
    ```
  </CodeGroup>

  To learn more, read [`Components.dataSystem()`](https://launchdarkly.github.io/android-client-sdk/com/launchdarkly/sdk/android/Components.html#dataSystem--). To learn more about additional configuration options, read [`DataSystemBuilder`](https://launchdarkly.github.io/android-client-sdk/com/launchdarkly/sdk/android/integrations/DataSystemBuilder.html).
</Accordion>

### Flutter

<Accordion title="Expand Flutter SDK code sample">
  <Warning>
    **Consider mobile update tails before shipping EAP code**

    Mobile applications have long update tails. Apps you ship today may remain installed on end-user devices for years. If you include the EAP version of the Flutter SDK in a production release, the EAP-era API surface and behaviors may persist in deployed apps long after data saving mode graduates to General Availability. Make sure your release timeline can tolerate shipping a non-stable API.
  </Warning>

  To enable data saving mode:

  1. Upgrade your Flutter SDK to version 4.20 or later.
  2. Request to [join the Early Access Program](mailto:product@launchdarkly.com). Wait to receive confirmation from LaunchDarkly that data saving mode is enabled for your account.
  3. Update your SDK configuration to enable the `dataSystem` configuration option.

  Here's how to enable the `dataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```dart title="Flutter SDK v4.20+" lines wrap theme={null}
    final config = LDConfig(
      CredentialSource.fromEnvironment(),
      AutoEnvAttributes.enabled,
      dataSystem: const DataSystemConfig(),
    );
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. The Flutter SDK uses streaming in the foreground for real-time flag updates and reduces activity in the background, and switches between connection modes automatically as the app moves between the foreground and background.

  #### Set a fixed connection mode

  To keep the SDK in a single connection mode instead of letting it manage the connection, set the initial connection mode. This applies as a sticky override that suppresses automatic mode switching until you clear it with `setConnectionMode`:

  <CodeGroup>
    ```dart title="Flutter SDK v4.20+" lines wrap theme={null}
    final config = LDConfig(
      CredentialSource.fromEnvironment(),
      AutoEnvAttributes.enabled,
      dataSystem: const DataSystemConfig(
        initialConnectionMode: ConnectionModeId.polling,
      ),
    );
    ```
  </CodeGroup>

  To learn more, read the [`launchdarkly_flutter_client_sdk` API documentation](https://pub.dev/documentation/launchdarkly_flutter_client_sdk/latest/).
</Accordion>

### JavaScript

<Accordion title="Expand JavaScript SDK code sample">
  To enable data saving mode:

  1. Upgrade your JavaScript SDK to version 4.9 or later.
  2. Request to [join the Early Access Program](mailto:product@launchdarkly.com). Wait to receive confirmation from LaunchDarkly that data saving mode is enabled for your account.
  3. Update your SDK configuration to enable the `dataSystem` configuration option.

  Here's how to enable the `dataSystem` configuration option:

  #### Standard setup

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

    const client = createClient('example-client-side-id', context, {
      dataSystem: {},
    });
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. The JavaScript SDK opens a streaming connection for real-time flag updates, and falls back to polling when streaming is unavailable.

  #### Set a fixed connection mode

  To keep the SDK in a single connection mode instead of letting it manage the connection, use manual mode switching and set the initial connection mode:

  <CodeGroup>
    ```js title="JavaScript SDK v4.9+" lines wrap theme={null}
    const client = createClient('example-client-side-id', context, {
      dataSystem: {
        automaticModeSwitching: { type: 'manual', initialConnectionMode: 'polling' },
      },
    });
    ```
  </CodeGroup>

  To learn more, read [`LDOptions.dataSystem`](https://launchdarkly.github.io/js-core/packages/sdk/browser/docs/interfaces/LDOptions.html#dataSystem).
</Accordion>

### React Native

<Accordion title="Expand React Native SDK code sample">
  <Warning>
    **Consider mobile update tails before shipping EAP code**

    Mobile applications have long update tails. Apps you ship today may remain installed on end-user devices for years. If you include the EAP version of the React Native SDK in a production release, the EAP-era API surface and behaviors may persist in deployed apps long after data saving mode graduates to General Availability. Make sure your release timeline can tolerate shipping a non-stable API.
  </Warning>

  To enable data saving mode:

  1. Upgrade your React Native SDK to version 10.19 or later.
  2. Request to [join the Early Access Program](mailto:product@launchdarkly.com). Wait to receive confirmation from LaunchDarkly that data saving mode is enabled for your account.
  3. Update your SDK configuration to enable the `dataSystem` configuration option.

  Here's how to enable the `dataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```js title="React Native SDK v10.19+" lines wrap theme={null}
    import { AutoEnvAttributes, ReactNativeLDClient } from '@launchdarkly/react-native-client-sdk';

    const client = new ReactNativeLDClient('example-mobile-key', AutoEnvAttributes.Enabled, {
      dataSystem: {},
    });
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. The React Native SDK uses streaming in the foreground for real-time flag updates and polling in the background, and switches between connection modes automatically as the app moves between the foreground and background.

  #### Automatic mode switching

  By default, the React Native SDK switches between connection modes automatically based on app lifecycle. To disable automatic switching entirely and keep the SDK in a single connection mode regardless of lifecycle changes:

  <CodeGroup>
    ```js title="React Native SDK v10.19+" lines wrap theme={null}
    const client = new ReactNativeLDClient('example-mobile-key', AutoEnvAttributes.Enabled, {
      dataSystem: {
        automaticModeSwitching: false,
      },
    });
    ```
  </CodeGroup>

  To learn more, read [`LDOptions.dataSystem`](https://launchdarkly.github.io/js-core/packages/sdk/react-native/docs/interfaces/LDOptions.html#dataSystem).
</Accordion>

### React Web

<Accordion title="Expand React Web SDK code sample">
  The React Web SDK is built on the JavaScript SDK, so it supports the same `dataSystem` configuration. Pass the option through the provider's `ldOptions`.

  To enable data saving mode:

  1. Upgrade your React Web SDK to version 4.2 or later.
  2. Request to [join the Early Access Program](mailto:product@launchdarkly.com). Wait to receive confirmation from LaunchDarkly that data saving mode is enabled for your account.
  3. Update your SDK configuration to enable the `dataSystem` configuration option.

  Here's how to enable the `dataSystem` configuration option:

  #### Standard setup

  <CodeGroup>
    ```js title="React Web SDK v4.2+" lines wrap theme={null}
    import { createLDReactProvider } from '@launchdarkly/react-sdk';

    export const LDReactProvider = createLDReactProvider('example-client-side-id', context, {
      ldOptions: { dataSystem: {} },
    });
    ```
  </CodeGroup>

  We recommend the standard data system configuration for most customers. The React Web SDK opens a streaming connection for real-time flag updates, and falls back to polling when streaming is unavailable.

  #### Set a fixed connection mode

  To keep the SDK in a single connection mode instead of letting it manage the connection, use manual mode switching and set the initial connection mode:

  <CodeGroup>
    ```js title="React Web SDK v4.2+" lines wrap theme={null}
    export const LDReactProvider = createLDReactProvider('example-client-side-id', context, {
      ldOptions: {
        dataSystem: { automaticModeSwitching: { type: 'manual', initialConnectionMode: 'polling' } },
      },
    });
    ```
  </CodeGroup>

  To learn more, read [`LDReactClientOptions`](https://launchdarkly.github.io/js-core/packages/sdk/react/docs/interfaces/client.LDReactClientOptions.html).
</Accordion>

### Vue

<Accordion title="Expand Vue code sample">
  The Vue SDK relies on the [JavaScript SDK](#javascript) for data saving mode, so it supports the same `dataSystem` configuration. Set the option in `ldOptions` when you install the plugin or create a provider.
</Accordion>
