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

# Offline mode

<View title="Developer" />

<View title="Federal docs" />

<View title="EU docs" />

This topic explains how to set an SDK to offline mode. Offline mode closes an SDK's connection to LaunchDarkly and switches to a feature flag's last known values.

## Fallback values and client-side SDKs

For client-side SDKs, if LaunchDarkly is unreachable or if an end user’s device is not connected to a network, such as when the device is in airplane mode, the SDK uses the latest stored flag variation values in memory. If there are no previously stored variation values, the SDK uses the fallback values that you define in your code.

In some situations, you might want to avoid remote calls to LaunchDarkly and use fallback values for your feature flags. For example, if your software is both cloud-hosted and distributed to customers to run on-premises, it might make sense to use fallback values when running on-premises. You can do this by setting offline mode in the client's config object. When the client is in offline mode, it makes no network requests, so it is suitable for unit-testing.

Details about each SDK's configuration are available in the SDK-specific sections below.

* [Client-side SDKs](#client-side-sdks)
* [Server-side SDKs](#server-side-sdks)

## Client-side SDKs

This feature is available in the following client-side SDKs:

* [.NET (client-side)](#net-client-side)
* [Android](#android)
* [C++ (client-side)](#c++-client-side)
* [Flutter](#flutter)
* [iOS](#ios)
* [React Native](#react-native)

### .NET (client-side)

<Accordion title="Expand .NET (client-side) code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```csharp title="C#" lines wrap theme={null}
    var config = Configuration
        .Builder("example-mobile-key", ConfigurationBuilder.AutoEnvAttributes.Enabled)
        .Offline(true)
        .Build();
    LdClient client = LdClient.Init(config, context, TimeSpan.FromSeconds(10));
    ```
  </CodeGroup>
</Accordion>

### Android

<Accordion title="Expand Android code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```java title="Android SDK v5.x (Java)" lines wrap theme={null}
    LDConfig ldConfig = new LDConfig.Builder(AutoEnvAttributes.Enabled)
        .mobileKey("example-mobile-key")
        .offline(true)
        .build();

    LDClient client = LDClient.init(this.getApplication(), ldConfig, context, 0);

    // Or to switch an already-instantiated client to offline mode:
    client.setOffline();
    ```

    ```kotlin title="Android SDK v5.x (Kotlin)" lines wrap theme={null}
    val config: LDConfig = LDConfig.Builder(AutoEnvAttributes.Enabled)
        .mobileKey("example-mobile-key")
        .offline(true)
        .build()

    val client: LDClient = LDClient.init(application, config, context, 0);

    // Or to switch an already-instantiated client to offline mode:
    client.setOffline()
    ```
  </CodeGroup>
</Accordion>

### C++ (client-side)

<Accordion title="Expand C++ (client-side) code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly. You can set the SDK offline, and no data will come into or out of the SDK. All flags will return the fallback values defined in your code.

  Here's how:

  <CodeGroup>
    ```cpp title="C++ SDK v3.0 (native)" lines wrap theme={null}
    config_builder.Offline(true);
    ```

    ```c title="C++ SDK v3.0 (C binding)" lines wrap theme={null}
    LDClientConfigBuilder_Offline(config_builder, true);
    ```
  </CodeGroup>
</Accordion>

### Flutter

<Accordion title="Expand Flutter code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```dart title="Flutter SDK v4" expandable lines wrap theme={null}
    final config = LDConfig(
      CredentialSource.fromEnvironment(),
      AutoEnvAttributes.enabled,
      dataSourceConfig: DataSourceConfig(
        initialConnectionMode: ConnectionMode.streaming // or .polling, or .offline
      ),
    );

    final client = LDClient(config, context);
    await client.start();

    // To switch an already-instantiated client to offline mode:
    client.offline = true;

    // To switch it back:
    client.offline = false;
    ```
  </CodeGroup>

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

### iOS

<Accordion title="Expand iOS code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  The SDK protects itself from multiple rapid calls to `setOnline(true)` by enforcing an increasing delay (called *throttling*) each time `setOnline(true)` is called within a short time. The first time, the call proceeds normally. For each subsequent call, the delay is enforced, and if waiting, increased to a maximum delay. When the delay has elapsed, the `setOnline(true)` proceeds, assuming that the client app has not called `setOnline(false)` during the delay. Therefore, a call to `setOnline(true)` may not immediately result in the LDClient going online.

  Client app developers should consider this situation abnormal, and take steps to prevent the client app from making multiple rapid `setOnline(true)` calls. Calls to `setOnline(false)` are not throttled. Calls to `start(config: context: completion:)`, and setting the `config` or `context` can also call `setOnline(true)` under certain conditions. After the delay, the SDK resets and the client app can make a subsequent call to `setOnline(true)` without being throttled.

  Client apps can set a completion closure called when the setOnline call completes. For unthrottled `setOnline(true)` and all `setOnline(false)` calls, the SDK calls the closure immediately on completion of this method. For throttled `setOnline(true)` calls, the SDK calls the closure after the throttling delay at the completion of the `setOnline` method.

  The SDK does not go online if the client has not been started, or the `mobileKey` is empty. For macOS, the SDK does not go online in the background unless `enableBackgroundUpdates` is true.

  Use `isOnline` to get the online/offline state.

  Here is an example:

  <CodeGroup>
    ```swift title="Swift" lines wrap theme={null}
    LDClient.get()!.setOnline(false)
    LDClient.get()!.setOnline(true) {
        // Client is online
    }
    let connectionStatus = LDClient.get()!.isOnline
    ```

    ```objectivec title="Objective-C" lines wrap theme={null}
    [[LDClient get] setOnline:NO];
    [[LDClient get] setOnline:YES completion:^() {
        // Client is online
    }];
    ```
  </CodeGroup>
</Accordion>

### React Native

<Accordion title="Expand React Native code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Use `setConnectionMode` to do this. The following connection modes are supported:

  * `offline`. In this connection mode, the SDK stops receiving updates and stops sending analytic and diagnostic events.
  * `streaming`. In this connection mode, the SDK uses a streaming connection to receive updates from LaunchDarkly. This is the default.

  Here's how:

  <CodeGroup>
    ```ts title="React Native SDK, v10" lines wrap theme={null}
    await client.setConnectionMode('offline');

    await client.setConnectionMode('streaming');
    ```
  </CodeGroup>

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

## Server-side SDKs

This feature is available in the following server-side SDKs:

* [.NET (server-side)](#net-server-side)
* [C++ (server-side)](#c++-server-side)
* [Erlang](#erlang)
* [Go](#go)
* [Haskell](#haskell)
* [Java](#java)
* [Lua](#lua)
* [Node.js (server-side)](#node-js-server-side)
* [PHP](#php)
* [Python](#python)
* [Ruby](#ruby)
* [Rust](#rust)

### .NET (server-side)

<Accordion title="Expand .NET (server-side) code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```csharp title="C#" lines wrap theme={null}
    var config = Configuration.Builder("YOUR_SDK_KEY")
        .Offline(true)
        .Build();
    LdClient client = new LdClient(config);
    ```
  </CodeGroup>
</Accordion>

### C++ (server-side)

<Accordion title="Expand C++ (server-side) code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly. You can set the SDK offline, and no data will come into or out of the SDK. All flags will return the fallback values defined in your code.

  Offline mode in the C++ server-side SDK is a shorthand for manually disabling events (`config_builder.Events().Disable()`) and the SDK's Data System (`config_builder.DataSystem().Disable()`).

  Here's how:

  <CodeGroup>
    ```cpp title="C++ SDK v3.0 (native)" lines wrap theme={null}
    config_builder.Offline(true);
    ```

    ```c title="C++ SDK v3.0 (C binding)" lines wrap theme={null}
    LDServerConfigBuilder_Offline(config_builder, true);
    ```
  </CodeGroup>
</Accordion>

### Erlang

<Accordion title="Expand Erlang code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```erlang title="Erlang" lines wrap theme={null}
    ldclient:start_instance("YOUR_SDK_KEY", #{offline => true})
    ```
  </CodeGroup>
</Accordion>

### Go

<Accordion title="Expand Go code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```go title="Go SDK v7.13.4+, using LDScopedClient" lines wrap theme={null}
    var config ld.Config
    config.Offline = true

    client, _ := ld.MakeCustomClient("YOUR_SDK_KEY", config, 5*time.Second)
    scopedClient := ld.NewScopedClient(client, context)
    // LDScopedClient is in beta and may change without notice.

    scopedClient.BoolVariation("example-flag-key", false) // will always return the default value (false)
    ```

    ```go title="Go SDK v6.x+, using LDClient" lines wrap theme={null}
    var config ld.Config
    config.Offline = true

    client, _ := ld.MakeCustomClient("YOUR_SDK_KEY", config, 5*time.Second)
    client.BoolVariation("any.feature.flag", context, false) // will always return the default value (false)
    ```
  </CodeGroup>
</Accordion>

### Haskell

<Accordion title="Expand Haskell code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```haskell title="Haskell" lines wrap theme={null}
    config' = configSetOffline True config
    ```
  </CodeGroup>
</Accordion>

### Java

<Accordion title="Expand Java code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```java title="Java SDK v6.0+" lines wrap theme={null}
    LDConfig config = new LDConfig.Builder()
      .offline(true)
      .build();
    LDClient client = new LDClient("YOUR_SDK_KEY", config);
    client.boolVariation("example-flag-key", context, false);

    // This call to client.boolVariation always
    // returns the default value (false)

    ```
  </CodeGroup>
</Accordion>

### Lua

<Accordion title="Expand Lua code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly. You can set the SDK offline, and no data will come into or out of the SDK. All flags will return the fallback values defined in your code.

  Here's how:

  <CodeGroup>
    ```lua title="Lua SDK v2" lines wrap theme={null}
    local config = {
        offline = true
    }
    ```
  </CodeGroup>
</Accordion>

### Node.js (server-side)

<Accordion title="Expand Node.js (server-side) code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```ts title="Node.js SDK v8.x+ (TypeScript)" lines wrap theme={null}
    import { LDOptions, init } from '@launchdarkly/node-server-sdk';

    const options: LDOptions = { offline: true };
    const client = init('YOUR_SDK_KEY', options);
    client.variation('any.feature.flag', context, false, cb); // cb will always be invoked with the default value (false)
    ```
  </CodeGroup>

  The default value you set in the variation method is returned in offline mode. This does not refer to the default rule set in your flag configuration.
</Accordion>

### PHP

<Accordion title="Expand PHP code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```php title="PHP SDK v5.0+" lines wrap theme={null}
    $client = new LaunchDarkly\LDClient("YOUR_SDK_KEY", ["offline" => true]);
    $client->variation("any.feature.flag", $context, false); // will always return the default value (false)
    ```
  </CodeGroup>
</Accordion>

### Python

<Accordion title="Expand Python code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```python title="Python SDK v8.0+" lines wrap theme={null}
    # Initialization:
    ldclient.set_config(Config("YOUR_SDK_KEY", offline=True))
    ldclient.get().variation("any.feature.flag", context, False) # will always return the default value (false)

    ```
  </CodeGroup>
</Accordion>

### Ruby

<Accordion title="Expand Ruby code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```ruby title="Ruby SDK v7.0+" lines wrap theme={null}
    config = LaunchDarkly::Config.new({offline: true})
    client = LaunchDarkly::LDClient.new("YOUR_SDK_KEY", config)
    client.variation("any.feature.flag", context, false) # will always return the default value (false)
    ```
  </CodeGroup>
</Accordion>

### Rust

<Accordion title="Expand Rust code sample">
  In some situations, you might want to stop making remote calls to LaunchDarkly and rely on locally cached flag values for future evaluations.

  Here's how:

  <CodeGroup>
    ```rust title="Rust SDK v1+" lines wrap theme={null}
    let config = ConfigBuilder::new("YOUR_SDK_KEY").offline(true).build().unwrap();
    let ld_client = Client::build(config).unwrap();
    ld_client.bool_variation(&context, "example-flag-key", false); // will always return the default value (false)
    ```
  </CodeGroup>
</Accordion>
