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

# Reading flags from a file

> This topic explains how to run feature flags from a file when you're using a server-side SDK.

> For the complete documentation index, see [llms.txt](/llms.txt). For the full documentation snapshot, see [llms-full.txt](/llms-full.txt).

## Overview

This topic explains how to run feature flags from a file when you're using a server-side SDK.

<Warning title="Do not use file-based flag values in production environments">
  Always configure production environments to receive flag updates from LaunchDarkly. Only use file-based flags in testing and pre-production environments, or in local development. We do not support using flags from files in a production environment.

  If you use flags from files in a production environment, you need to propagate flag changes to the file whenever one of your flags is updated in the LaunchDarkly UI.
</Warning>

If you perform automated tests or prototyping, you might want to run application code that uses feature flags without connecting to LaunchDarkly. LaunchDarkly SDKs in offline mode return the fallback value for each flag evaluation. This is not a property of the flag. It is the value that you specified as a fallback in your program code when you evaluated the flag.

However, in some server-side SDKs, you can use files to configure the feature flag state you desire instead of offline mode. Offline mode uses only fallback values.

<Note title="Reading flags from files is only available for server-side SDKs">
  If you are looking for other ways to test server-side SDKs, you can also use [Test data sources](/sdk/features/test-data-sources).

  If you are looking for ways to test client-side SDKs, consider [Test data sources](/sdk/features/test-data-sources) or [Unit testing with Jest](/guides/sdk/unit-tests) instead. To learn more, read [Testing code that uses feature flags](/guides/flags/testing-code).
</Note>

<Note title="Newer versions of LaunchDarkly SDKs replace users with contexts">
  A context is a generalized way of referring to the people, services, machines, or other resources that encounter feature flags in your product. Contexts replace another data object in LaunchDarkly: "users." To learn more, read [Contexts](/home/flags/contexts).

  Creating contexts and evaluating flags based on them is supported in the latest major versions of [most of our SDKs](/sdk). For these SDKs, the code samples on this page include the two most recent versions.
</Note>

## Create a flag data file

Flag data files can be either JSON or YAML.

They contain up to three properties:

* `flags`: These are feature flag definitions. These can contain all the same kinds of rules and targets that you can define in a LaunchDarkly feature flag, which allows the flag to produce different values for different contexts or users.
* `flagValues`: These are simplified feature flags that specify only a value, and produce the same value for all contexts or users.
* `segments`: These are segment definitions. You only use this property if you have feature flags that use segments.

<Note title="Only standard segments are supported in files">
  Only rule-based segments and smaller list-based segments are supported in the file definition. Synced segments and larger list-based segments, collectively known as big segments, cannot be read from files. To learn more, read [Segments](/home/flags/segments).
</Note>

<Warning title="YAML files have limitations">
  In some of the SDKs, YAML support requires an additional dependency. YAML is not available in PHP or C++.
</Warning>

The format of the data in `flags` and `segments` is defined by the LaunchDarkly application and is subject to change. Rather than trying to construct these objects yourself, it's simpler to request existing flags directly from the LaunchDarkly server in JSON format and use this output as the starting point for your file.

Get the flags from the appropriate endpoint for your instance, or the `/sdk/poll` endpoint if using [data saving mode](/sdk/features/data-saving-mode). Pass your SDK key in the `Authorization` header:

* **Commercial**: `https://sdk.launchdarkly.com/sdk/latest-all`
* **Federal**: `https://sdk.launchdarkly.us/sdk/latest-all`
* **EU**: `https://sdk.eu.launchdarkly.com/sdk/latest-all`

For instance, in your terminal, you could use this command:

<CodeGroup>
  ```bash title="Console" theme={null}
      curl -H "Authorization: YOUR_SDK_KEY" https://sdk.launchdarkly.com/sdk/latest-all >flagdata.json
  ```

  ```bash title="Console, federal" theme={null}
      curl -H "Authorization: YOUR_SDK_KEY" https://sdk.launchdarkly.us/sdk/latest-all >flagdata.json
  ```

  ```bash title="Console, EU" theme={null}
      curl -H "Authorization: YOUR_SDK_KEY" https://sdk.eu.launchdarkly.com/sdk/latest-all >flagdata.json
  ```
</CodeGroup>

The output looks like this, but with many more properties:

<CodeGroup>
  ```json title="JSON output" theme={null}
      {
        "flags": {
          "flag-key-1": {
            "key": "flag-key-1",
              "on": true,
              "variations": [ "a", "b" ]
            }
        },
        "segments": {
          "segment-key-1": {
            "key": "segment-key-1",
            "includes": [ "context-key-1" ]
          }
        }
      }
  ```
</CodeGroup>

Data in this format lets the SDK exactly duplicate all the kinds of flag behavior LaunchDarkly supports. However, in most cases you do not need this level of complexity. You may want to simply set specific flag keys to specific values.

For that, you can use a much simpler format.

Here's how:

<CodeGroup>
  ```json title="JSON" theme={null}
      {
        "flagValues": {
          "my-string-flag-key": "value-1",
          "my-boolean-flag-key": true,
          "my-integer-flag-key": 3
        }
      }
  ```

  ```yaml title="YAML" theme={null}
      flagValues:
        my-string-flag-key: "value-1"
        my-boolean-flag-key: true
        my-integer-flag-key: 3
  ```
</CodeGroup>

If you want some flags to have simple values and others to have complex behavior, you can specify both `flags` and `flagValues`. However, it generates an error if you use the same flag key or segment key more than once, either in a single file or across multiple files.

## Configure the client to use a file

You can specify either a single file or multiple files. In all of the SDKs that support this feature except Haskell, PHP, and C++, you can also specify whether the SDK should reload the file data if it detects that you have modified a file. For example, you could verify that your application behaves correctly when a flag changes.

The examples below show how to configure the client to use two data files called `file1.json` and `file2.json`. The client assumes these two files are in the current working directory, but you can specify any relative or absolute file path. It also enables automatic reloading, if supported.

If you do not want your code to connect to LaunchDarkly at all, you must also prevent the SDK from sending analytics events. We've included the option to disable events in these examples.

Because there is no connection to LaunchDarkly, you do not have to use a valid SDK key. The SDK key parameter is still required, but you can use any string.

If any of the specified files is missing or invalid, the SDK does not use any of the file data and logs an error message instead.

## Server-side SDKs

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

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

### .NET (server-side)

<Accordion title="Expand .NET (server-side) code sample">
  To configure the client:

  <CodeGroup>
    ```csharp title="C#" theme={null}
          using LaunchDarkly.Sdk.Server;
          using LaunchDarkly.Sdk.Server.Integrations;

          var config = Configuration.Builder("sdk key")
              .DataSource(
                  FileData.DataSource()
                      .FilePaths("file1.json", "file2.json")
                      .AutoUpdate(true)
              )
              .Events(Components.NoEvents())
              .Build()

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

  If you want to use YAML instead of JSON, you must [provide a YAML parser](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.Server.Integrations.FileDataSourceBuilder.html#LaunchDarkly_Sdk_Server_Integrations_FileDataSourceBuilder_Parser_).

  To learn more, read [`FileData`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.Server.Integrations.FileData.html).
</Accordion>

### C++ (server-side)

<Accordion title="Expand C++ code sample">
  To configure the client:

  <CodeGroup>
    ```c title="C++" theme={null}
          #include <launchdarkly/integrations/file_data.h>

          const char *filenames[2] = {
              "file1.json",
              "file2.json"
          };
          LDConfigSetDataSource(config, LDFileDataInit(2, filenames));
          LDConfigSetSendEvents(config, LDBooleanFalse);

          // Call LDClientInit with config as usual.
    ```
  </CodeGroup>

  To learn more, read [`LDFileDataInit`](https://launchdarkly.github.io/c-server-sdk/file__data_8h.html).
</Accordion>

### Erlang

<Accordion title="Expand Erlang code sample">
  To configure the client:

  <CodeGroup>
    ```erlang title="Erlang" theme={null}
            ldclient:start_instance("YOUR_SDK_KEY", #{
              file_datasource => true,
              send_events => false,
              file_paths => ["file1.json", "file2.yaml"],
              feature_store => ldclient_storage_map,
              file_auto_update => true,
              file_poll_interval => 1000
            })

            %% In the Erlang SDK automatic reloading uses a polling mechanism.
            %% The default interval is 1000ms, but you can control it with
            %% the file_poll_interval configuration.
    ```
  </CodeGroup>
</Accordion>

### Go

<Accordion title="Expand Go code sample">
  <CodeGroup>
    ```go title="Go SDK v6.0" theme={null}
          import (
              "time"

              ld "github.com/launchdarkly/go-server-sdk/v6"
              "github.com/launchdarkly/go-server-sdk/v6/ldcomponents"
              "github.com/launchdarkly/go-server-sdk/v6/ldfiledata"
              "github.com/launchdarkly/go-server-sdk/v6/ldfilewatch"
          )

          var config ld.Config
          config.DataSource = ldfiledata.DataSource().
              FilePaths("file1.json", "file2.json").
              Reloader(ldfilewatch.WatchFiles)
          config.Events = ldcomponents.NoEvents()

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

### Haskell

<Accordion title="Expand Haskell code sample">
  To configure the client:

  <CodeGroup>
    ```haskell title="Haskell" theme={null}
          let config = LD.configSetDataSourceFactory (Just $ FileData.dataSourceFactory ["./testData/flags.json"]) $ LD.makeConfig "YOUR_SDK_KEY"
          client <- LD.makeClient config
    ```
  </CodeGroup>
</Accordion>

### Java

<Accordion title="Expand Java code sample">
  To configure the client:

  <CodeGroup>
    ```java title="Java" theme={null}
          import com.launchdarkly.sdk.server.*;
          import com.launchdarkly.sdk.server.integrations.*;

          LDConfig config = new LDConfig.Builder()
            .dataSource(
              FileData.dataSource()
                .filePaths("file1.json", "file2.json")
                .autoUpdate(true)
            )
            .events(Components.noEvents())
            .build();

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

  To learn more, read [`FileData`](https://launchdarkly.github.io/java-core/lib/sdk/server/com/launchdarkly/sdk/server/integrations/FileData.html).
</Accordion>

### Node.js (server-side)

<Accordion title="Expand Node.js (server-side) code sample">
  To configure the client:

  <CodeGroup>
    ```js title="Node.js SDK v8.x (JavaScript)" theme={null}
          import { init } from '@launchdarkly/node-server-sdk');
          import { FileDataSourceFactory } from '@launchdarkly/node-server-sdk/integrations';

          const fileData = new FileDataSourceFactory({
            paths: [ 'file1.json', 'file2.json' ]
          });

          const options = {
            updateProcessor: fileData.getFactory()
          };

          const client = init('YOUR_SDK_KEY', options);
    ```

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

          const fileData = new FileDataSourceFactory({
            paths: [ 'file1.json', 'file2.json' ],
          });

          const options: LDOptions = {
            updateProcessor: fileData.getFactory()
          };

          const client = init('YOUR_SDK_KEY', options);
    ```

    ```js title="Node.js SDK v7.x (JavaScript)" theme={null}
          const ld = require('launchdarkly-node-server-sdk');
          const { FileDataSource } = require('launchdarkly-node-server-sdk/integrations');

          const dataSource = FileDataSource({
            paths: [ 'file1.json', 'file2.json' ]
          });

          const options = {
            updateProcessor: dataSource
          };

          const client = ld.init('YOUR_SDK_KEY', options);
    ```

    ```ts title="Node.js SDK v7.x (TypeScript)" theme={null}
          import { LDOptions, init } from 'launchdarkly-node-server-sdk';
          import { FileDataSource } from 'launchdarkly-node-server-sdk/integrations';

          const dataSource = FileDataSource({
            paths: [ 'file1.json', 'file2.json' ],
          });

          const options: LDOptions = {
            updateProcessor: dataSource
          };

          const client = init('YOUR_SDK_KEY', options);
    ```
  </CodeGroup>

  To learn more, read [`FileDataSourceFactory`](https://launchdarkly.github.io/js-core/packages/sdk/server-node/docs/classes/integrations.FileDataSourceFactory.html).
</Accordion>

### PHP

<Accordion title="Expand PHP code sample">
  To configure the client:

  <CodeGroup>
    ```php title="PHP" theme={null}
          // Automatic reloading is not supported in PHP, because normally in PHP
          // the entire in-memory application state is recreated for each request.

          $fr = LaunchDarkly\Integrations\Files::featureRequester([
              'file1.json',
              'file2.json'
          ]);
          $client = new LaunchDarkly\LDClient("YOUR_SDK_KEY", [
              'feature_requester' => $fr,
              'send_events' => false
          ]);
    ```
  </CodeGroup>

  To learn more, read [`Files`](https://launchdarkly.github.io/php-server-sdk/classes/LaunchDarkly-Integrations-Files.html).
</Accordion>

### Python

<Accordion title="Expand Python code sample">
  To configure the client:

  <CodeGroup>
    ```python title="Python" theme={null}
          import ldclient
          from ldclient.config import Config
          from ldclient.integrations import Files

          data_source_callback = Files.new_data_source(paths=["file1.json", "file2.json"],
              auto_update=True)

          config = Config('YOUR_SDK_KEY', update_processor_class=data_source_callback, send_events=False)

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

  In the Python SDK, if you want to use YAML files instead of JSON you must install the `pyyaml` package. Also, automatic reloading uses an inefficient file-polling mechanism. We recommend installing the `watchdog` package.

  To learn more, read [`Files`](https://launchdarkly-python-sdk.readthedocs.io/en/latest/api-integrations.html#ldclient.integrations.Files).
</Accordion>

### Ruby

<Accordion title="Expand Ruby code sample">
  To configure the client:

  <CodeGroup>
    ```ruby title="Ruby" theme={null}
          require 'ldclient-rb'

          data_source = LaunchDarkly::Integrations::FileData.data_source(
            paths: [ "file1.json", "file2.json" ],
            auto_update: true
          )

          config = LaunchDarkly::Config.new(
            data_source: data_source,
            send_events: false
          )

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

  In the Ruby SDK, automatic reloading uses an inefficient file-polling mechanism unless you install the `listen` gem.

  To learn more, read [`FileData`](https://launchdarkly.github.io/ruby-server-sdk/LaunchDarkly/Integrations/FileData.html).
</Accordion>
