• Home
  • Integrations
  • SDKs
  • Guides
  • API docs
No results for ""
EXPAND ALL

EDIT ON GITHUB

Reading flags from a file

Read time: 3 minutes
Last edited: Oct 19, 2021

Overview

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

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

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 default value for each flag evaluation. Default is not an actual 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 also use files to configure the feature flag state you desire.

Creating 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 users.
  • flagValues: These are simplified feature flags that specify only a value, and produce the same value for all users.
  • segments: These are user segment definitions. You only use this property if you have feature flags that use segments.
YAML files have limitations

In some of the SDKs, YAML support requires an additional dependency. YAML is not available in PHP.

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 https://app.launchdarkly.com/sdk/latest-all. Pass your SDK key in the Authorization header.

For instance, in Linux, you could use this command:

1curl -H "Authorization: EXAMPLE_SDK_KEY" https://app.launchdarkly.com/sdk/latest-all >flagdata.json

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

1{
2 "flags": {
3 "flag-key-1": {
4 "key": "flag-key-1",
5 "on": true,
6 "variations": [ "a", "b" ]
7 }
8 },
9 "segments": {
10 "segment-key-1": {
11 "key": "segment-key-1",
12 "includes": [ "user-key-1" ]
13 }
14 }
15}

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:

1{
2 "flagValues": {
3 "my-string-flag-key": "value-1",
4 "my-boolean-flag-key": true,
5 "my-integer-flag-key": 3
6 }
7}

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.

Configuring 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 PHP, 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)
  • Erlang
  • Go
  • Java
  • Node.js (server-side)
  • Python
  • PHP
  • Ruby

.NET (server-side)

To configure the client:

1using LaunchDarkly.Sdk.Server;
2using LaunchDarkly.Sdk.Server.Integrations;
3
4var config = Configuration.Builder("sdk key")
5 .DataSource(
6 FileData.DataSource()
7 .FilePaths("file1.json", "file2.json")
8 .AutoUpdate(true)
9 )
10 .Events(Components.NoEvents())
11 .Build()
12
13var client = new LDClient(config);
14
15
16// Prior to version 6.0, use this syntax:
17
18using LaunchDarkly.Client;
19using LaunchDarkly.Client.Files;
20
21var fileSource = FileComponents.FileDataSource()
22 .WithFilePaths("file1.json", "file2.json")
23 .WithAutoUpdate(true);
24
25var config = Configuration.Builder("sdk key")
26 .UpdateProcessorFactory(fileSource)
27 .EventProcessorFactory(Components.NullEventProcessor)
28 .Build();
29
30var client = new LDClient(config);

To learn more, read FileData.

If you want to use YAML instead of JSON, you must provide a YAML parser.

Erlang

To configure the client:

1ldclient:start_instance("sdk key", #{
2 file_datasource => true,
3 send_events => false,
4 file_paths => ["file1.json", "file2.yaml"],
5 feature_store => ldclient_storage_map,
6 file_auto_update => true,
7 file_poll_interval => 1000
8 })
9
10 %% In the Erlang SDK automatic reloading uses a polling mechanism.
11 %% The default interval is 1000ms, but you can control it with
12 %% the file_poll_interval configuration.

Go

1import (
2 ld "gopkg.in/launchdarkly/go-server-sdk.v5"
3 "gopkg.in/launchdarkly/go-server-sdk.v5/ldcomponents"
4 "gopkg.in/launchdarkly/go-server-sdk.v5/ldfiledata"
5 "gopkg.in/launchdarkly/go-server-sdk.v4/ldfilewatch"
6)
7
8var config ld.Config
9config.DataSource = ldfiledata.DataSource().
10 FilePaths("file1.json", "file2.json").
11 UseReloader(ldfilewatch.WatchFiles)
12config.Events = ldcomponents.NoEvents()
13
14client := ld.MakeCustomClient("sdk key", config, 5*time.Second)
15
16
17// In versions earlier than 5.0, use this syntax:
18
19import (
20 ld "gopkg.in/launchdarkly/go-server-sdk.v4"
21 "gopkg.in/launchdarkly/go-server-sdk.v4/ldfiledata"
22 "gopkg.in/launchdarkly/go-server-sdk.v4/ldfilewatch"
23)
24
25fileSource, err := ldfiledata.NewFileDataSourceFactory(
26 ldfiledata.FilePaths("file1.json", "file2.json"),
27 ldfiledata.UseReloader(ldfilewatch.WatchFiles))
28
29config := ld.DefaultConfig
30config.UpdateProcessorFactory = fileSource
31config.SendEvents = false
32
33client := ld.MakeCustomClient("sdk key", config, 5*time.Second)

Java

To configure the client:

1import com.launchdarkly.sdk.server.*;
2import com.launchdarkly.sdk.server.integrations.*;
3
4LDConfig config = new LDConfig.Builder()
5 .dataSource(
6 FileData.dataSource()
7 .filePaths("file1.json", "file2.json")
8 .autoUpdate(true)
9 )
10 .events(Components.noEvents())
11 .build();
12
13LDClient client = new LDClient("sdk key", config);
14
15
16// In versions earlier than 5.0, use this syntax:
17
18import com.launchdarkly.client.*;
19import com.launchdarkly.client.files.*;
20
21FileDataSourceFactory fileSource = FileComponents.fileDataSource()
22 .filePaths("file1.json", "file2.json")
23 .autoUpdate(true);
24
25LDConfig config = new LDConfig.Builder()
26 .updateProcessorFactory(fileSource)
27 .sendEvents(false)
28 .build();
29
30LDClient client = new LDClient("sdk key", config);

To learn more, read FileData.

Node.js (server-side)

To configure the client:

1const LaunchDarkly = require('ldclient-node');
2
3const dataSource = LaunchDarkly.FileDataSource({
4 paths: [ "file1.json", "file2.json" ]
5});
6
7const config = {
8 updateProcessor: dataSource
9};
10
11const client = LaunchDarkly.init(sdkKey, config);

Python

To configure the client:

1import ldclient
2from ldclient.config import Config
3from ldclient.file_data_source import FileDataSource
4
5factory = FileDataSource.factory(paths=["file1.json", "file2.json"],
6 auto_update=True)
7
8config = Config(update_processor_class=factory, send_events=False)
9
10ldclient.set_config(config)
11ldclient.set_sdk_key("sdk key")
12client = ldclient.get()
13
14# In the Python SDK, if you want to use YAML files instead of JSON
15# you must install the "pyyaml" package. Also, automatic reloading uses an
16# inefficient file-polling mechanism. We recommend installing the "watchdog"
17# package.

PHP

To configure the client:

1// Automatic reloading is not supported in PHP, because normally in PHP
2// the entire in-memory application state is recreated for each request.
3
4$fr = LaunchDarkly\Integrations\Files::featureRequester([
5 'file1.json',
6 'file2.json'
7]);
8$client = new LaunchDarkly\LDClient("your_sdk_key", [
9 'feature_requester' => $fr,
10 'send_events' => false
11]);

Ruby

To configure the client:

1require 'ldclient-rb'
2
3factory = LaunchDarkly::FileDataSource.factory(
4 paths: [ "file1.json", "file2.json" ],
5 auto_update: true
6)
7
8config = LaunchDarkly::Config.new(
9 update_processor_factory: factory,
10 send_events: false
11)
12
13client = LaunchDarkly::Client.new("sdk key", config)
14
15# In the Ruby SDK, automatic reloading uses an inefficient
16# file-polling mechanism unless you install the "listen" gem.