• HOME
  • INTEGRATIONS
  • SDKS
  • GUIDES
  • API DOCS
No results for ""
EXPAND ALL

EDIT ON GITHUB

Storing data

Read time: 4 minutes
Last edited: Jul 28, 2021

Overview

This topic explains which external databases each server-side SDK can use to store flag data.

By default, all our SDKs work with an in-memory feature store. This feature store requires no additional configuration. However, data in in-memory feature stores are not persistent. This means when you restart your application, your SDK reloads the entire store's contents.

Persistent feature stores solve this problem by persisting their data so that they can be used across application restarts.

Using external databases as persistent feature stores

By default, LaunchDarkly's server-side SDKs connect to LaunchDarkly and receive feature flag data, store the flags in local memory, and update them when prompted to by LaunchDarkly. This collection of last known flag data is cached in the "feature store" or "data store."

To learn more, read Persistent data stores.

Alternatively, you can configure an external database to act as a feature store. The SDKs in this topic can use one or more of these three caching options to hold their flag data:

  • Consul
  • DynamoDB
  • Redis

Whichever database you use, there are two ways to use it:

  • Exactly like the default configuration, except substituting a database for the in-memory store, or
  • Using only the database as a source of flag data, without connecting to LaunchDarkly.

Using a persistent feature store while still connecting to LaunchDarkly

In this configuration, the SDK receives feature flag data from LaunchDarkly and puts it in the feature store. The only difference is that the store is in a database.

When flags are evaluated, the SDK checks the database to get the latest flag state, usually with some form of in-memory caching to improve performance.

The main reason to do this is to accelerate flag updates when your application has to restart, and after restarting, it takes longer to establish a connection to LaunchDarkly than you want. If you have a persistent feature store that has already been populated, the SDK can still evaluate flags using the last known flag state from the store until newer data is available from LaunchDarkly.

To set up this configuration, most people create some kind of object for the specific type of database and put it in the client configuration's feature store property. In PHP, this property is called the "feature requester".

If there are multiple instances of your application configured in this way with the same database, the same data gets written to the database multiple times, because each instance receives feature flags from LaunchDarkly. This is harmless, but it is inefficient, so you may want to use a persistent feature store without connecting to LaunchDarkly, as described below.

Using a persistent feature store without connecting to LaunchDarkly

This is similar to the previous configuration, except that the SDK does not connect to LaunchDarkly at all. Instead, it relies on some other process which does have a LaunchDarkly connection to write the latest flag data to the database, where the SDK will then read it.

The other process could be the Relay Proxy, or any other application that creates a SDK client with the same persistent store. To learn more about the Relay Proxy, read The Relay Proxy.

Since the Relay Proxy is also known as the LaunchDarkly Daemon, some versions of the SDKs refer to this mode as "LDD mode." Creating the client is the same as above in terms of specifying the persistent store, but you must also add an option to make the SDK not connect to LaunchDarkly.

Server-side SDKs

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

.NET

The .NET SDK can use Consul, DynamoDB, or Redis to hold flag data.

To use a persistent feature store while connecting to LaunchDarkly:

1using LaunchDarkly.Sdk.Server;
2using LaunchDarkly.Sdk.Server.Integrations;
3
4var config = Configuration.Builder(sdkKey)
5 .DataStore(
6 Components.PersistentDataStore(
7 SomeDatabaseName.DataStore()
8 )
9 )
10 .Build();

To learn more, read ConfigurationBuilder.DataStore.

To use a persistent feature store without connecting to LaunchDarkly:

1using LaunchDarkly.Sdk.Server;
2using LaunchDarkly.Sdk.Server.Integrations;
3
4var config = Configuration.Builder(sdkKey)
5 .DataStore(
6 Components.PersistentDataStore(
7 SomeDatabaseName.DataStore()
8 )
9 )
10 .DataSource(Components.ExternalUpdatesOnly)
11 .Build();

To learn more, read Components.ExternalUpdatesOnly.

C/C++ (server-side)

The C/C++ SDK can use Redis to hold flag data.

To use a persistent feature store while connecting to LaunchDarkly:

1#include <launchdarkly/api.h>
2
3struct LDConfig *config = LDConfigNew("my-key");
4
5struct LDStoreInterface *store = ConstructYourFeatureStoreInterface();
6
7LDConfigSetFeatureStoreBackend(config, store);

To use a persistent feature store without connecting to LaunchDarkly:

1#include <launchdarkly/api.h>
2
3struct LDConfig *config = LDConfigNew("my-key");
4
5struct LDStoreInterface *store = ConstructYourFeatureStoreInterface();
6
7LDConfigSetFeatureStoreBackend(config, store);
8LDConfigSetUseLDD(config, true); // <-- the extra option

Erlang

The Erlang SDK can use Redis to hold flag data.

To use a persistent feature store while connecting to LaunchDarkly:

1LdOptions = #{
2 feature_store => your_feature_store
3},
4ldclient:start_instance("your_sdk_key", LdOptions).

To use a persistent feature store without connecting to LaunchDarkly:

1LdOptions = #{
2 use_ldd => true,
3 feature_store => your_feature_store
4},
5ldclient:start_instance("your_sdk_key", LdOptions).

To learn more, read ldclient_config.

Go

The Go SDK can use Consul, DynamoDB, or Redis to hold flag data.

To use a persistent feature store while connecting to LaunchDarkly:

1import (
2 ld "gopkg.in/launchdarkly/go-server-sdk.v5"
3 "gopkg.in/launchdarkly/go-server-sdk.v5/ldcomponents"
4 examplepackage "github.com/launchdarkly/go-server-sdk-some-example-database"
5)
6
7var config ld.Config
8config.DataStore = ldcomponents.PersistentDataStore(
9 examplepackage.DataStore().SomeStoreOptions(),
10)
11client := ld.MakeCustomClient(sdkKey, config, waitTime)
12
13
14// Before version 5.0, the syntax was different:
15import (
16 ld "gopkg.in/launchdarkly/go-server-sdk.v4"
17 examplepackage "gopkg.in/launchdarkly/go-server-sdk.v4/some-example-database"
18)
19
20factory, err := examplepackage.NewExampleFeatureStoreFactory(someStoreOptions)
21config := ld.DefaultConfig
22config.FeatureStoreFactory = factory
23client := ld.MakeCustomClient(sdkKey, config, waitTime)

To learn more, read PersistentDataStore.

To use a persistent feature store without connecting to LaunchDarkly:

1import (
2 ld "gopkg.in/launchdarkly/go-server-sdk.v5"
3 "gopkg.in/launchdarkly/go-server-sdk.v5/ldcomponents"
4 examplepackage "github.com/launchdarkly/go-server-sdk-some-example-database"
5)
6
7var config ld.Config
8config.DataStore = ldcomponents.PersistentDataStore(
9 examplepackage.DataStore().SomeStoreOptions(),
10)
11config.DataSource = ldcomponents.ExternalUpdatesOnly() // <-- the extra option
12client := ld.MakeCustomClient(sdkKey, config, waitTime)
13
14
15// Before version 5.0, the syntax was different:
16import (
17 ld "gopkg.in/launchdarkly/go-server-sdk.v4"
18 examplepackage "gopkg.in/launchdarkly/go-server-sdk.v4/some-example-database"
19)
20
21factory, err := examplepackage.NewExampleFeatureStoreFactory(someStoreOptions)
22config := ld.DefaultConfig
23config.FeatureStoreFactory = factory
24config.UseLdd = true // <-- the extra option
25client := ld.MakeCustomClient(sdkKey, config, waitTime)

To learn more, read ExternalUpdatesOnly.

Haskell

The Haskell SDK can use Redis to hold flag data.

To use a persistent feature store while connecting to LaunchDarkly:

1import LaunchDarkly.Server
2
3main = do
4 backend <- makeYourBackendInterface
5
6 let config = configSetStoreBackend backend $ makeConfig "your_sdk_key"
7
8 client <- makeClient config

To use a persistent feature store without connecting to LaunchDarkly:

1import LaunchDarkly.Server
2
3main = do
4 backend <- makeYourBackendInterface
5
6 let config = configSetUseLdd True $ configSetStoreBackend backend $ makeConfig "your_sdk_key"
7
8 client <- makeClient config

Java

The Java SDK can use Consul, DynamoDB, or Redis to hold flag data.

To use a persistent feature store while connecting to LaunchDarkly:

1import com.launchdarkly.sdk.server.*;
2import com.launchdarkly.sdk.server.integrations.*;
3
4LDConfig config = new LDConfig.Builder()
5 .dataStore(
6 Components.persistentDataStore(
7 SomeDatabaseName.dataStore(storeOptions)
8 )
9 )
10 .build();
11LDClient client = new LDClient(sdkKey, config);
12
13
14// Before version 5.0, the syntax was different:
15import com.launchdarkly.client.*;
16import com.launchdarkly.client.integrations.*;
17
18LDConfig config = new LDConfig.Builder()
19 .featureStoreFactory(new SomeFeatureStoreBuilder(storeOptions))
20 .build();

To learn more, read Components.persistentDataStore.

To use a persistent feature store without connecting to LaunchDarkly:

1import com.launchdarkly.sdk.server.*;
2import com.launchdarkly.sdk.server.integrations.*;
3
4LDConfig config = new LDConfig.Builder()
5 .dataStore(
6 Components.persistentDataStore(
7 SomeDatabaseName.dataStore(storeOptions)
8 )
9 )
10 .dataSource(Components.externalUpdatesOnly()) // <-- the extra option
11 .build();
12LDClient client = new LDClient(sdkKey, config);
13
14
15// Before version 5.0, the syntax was different:
16
17import com.launchdarkly.client.*;
18
19LDConfig config = new LDConfig.Builder()
20 .featureStoreFactory(new SomeFeatureStoreBuilder(storeOptions))
21 .useLdd(true)
22 .build();

To learn more, read Components.externalUpdatesOnly.

Lua

The module launchdarkly_server_sdk_redis allows feature flag data to be cached with Redis. To learn more, read Redis.

To use a persistent feature store while connecting to LaunchDarkly:

1local l = require("launchdarkly_server_sdk")
2
3local backend = makeYourBackendInterface()
4
5local c = l.clientInit({
6 key = "your_sdk_key",
7 featureStoreBackend = backend
8)}

To use a persistent feature store without connecting to LaunchDarkly:

1local l = require("launchdarkly_server_sdk")
2
3local backend = makeYourBackendInterface()
4
5local c = l.clientInit({
6 key = "your_sdk_key",
7 featureStoreBackend = backend,
8 useLDD = true
9)}

Node.js (server-side)

The Node.js SDK can use Consul, DynamoDB, or Redis to hold flag data.

To use a persistent feature store while connecting to LaunchDarkly:

1const LaunchDarkly = require('launchdarkly-node-server-sdk');
2
3const store = SomeKindOfFeatureStore(storeOptions);
4const config = {
5 featureStore: store
6};
7const client = LaunchDarkly.init(sdkKey, config);

To use a persistent feature store without connecting to LaunchDarkly:

1const LaunchDarkly = require('launchdarkly-node-server-sdk');
2
3const store = SomeKindOfFeatureStore(storeOptions);
4const config = {
5 featureStore: store,
6 useLdd: true // the extra option
7};
8const client = LaunchDarkly.init(sdkKey, config);

PHP

The PHP SDK can use Consul, DynamoDB, or Redis to hold flag data.

To use a persistent feature store while connecting to LaunchDarkly:

1$client = new LaunchDarkly\LDClient("your_sdk_key", [
2 'feature_requester' => LaunchDarkly\Integrations\Redis::featureRequester()
3]);
4
5// Prior to version 3.5.0, use this syntax:
6// $client = new LaunchDarkly\LDClient("your_sdk_key", [
7// 'feature_requester_class' => 'LaunchDarkly\SomeKindOfFeatureRequester'
8// ]);

To use a persistent feature store without connecting to LaunchDarkly:

1/*
2 In PHP, there is no difference between this and the previous example, because
3 the PHP SDK can only either get flags from LaunchDarkly *or* get them from a
4 database, not both
5*/
6$client = new LaunchDarkly\LDClient("your_sdk_key", [
7 'feature_requester' => LaunchDarkly\Integrations\Redis::featureRequester()
8]);
9
10// Prior to version 3.5.0, use this syntax:
11// $client = new LaunchDarkly\LDClient("your_sdk_key", [
12// 'feature_requester_class' => 'LaunchDarkly\SomeKindOfFeatureRequester'
13// ]);

Python

The Python SDK can use Consul, DynamoDB, or Redis to hold flag data.

To use a persistent feature store while connecting to LaunchDarkly:

1import ldclient
2from ldclient.config import Config
3
4store = SomeKindOfFeatureStore(store_options)
5config = Config(feature_store=store)
6ldclient.set_config(config)

Using a persistent feature store without connecting to LaunchDarkly

1import ldclient
2from ldclient.config import Config
3
4store = SomeKindOfFeatureStore(store_options)
5config = Config(
6 feature_store=store,
7 use_ldd=True # <-- the extra option
8)
9ldclient.set_config(config)

Ruby

The Ruby SDK can use Consul, DynamoDB, or Redis to hold flag data.

These adapters are implemented in the LaunchDarkly::Integrations::Redis, LaunchDarkly::Integrations::DynamoDB, and LaunchDarkly::Integrations::Consul modules. To use them, call the new_feature_store method in the module, and put the returned object in the feature_store property of your client configuration.

To use a persistent feature store while connecting to LaunchDarkly:

1require 'ldclient-rb'
2
3store = SomeKindOfFeatureStore.new(storeOptions)
4config = LaunchDarkly::Config.new(
5 feature_store: store
6)
7client = LaunchDarkly::Client.new(sdk_key, config)

To use a persistent feature store without connecting to LaunchDarkly:

1require 'ldclient-rb'
2
3store = SomeKindOfFeatureStore.new(storeOptions)
4config = LaunchDarkly::Config.new(
5 feature_store: store,
6 use_ldd: true # <-- the extra option
7)
8client = LaunchDarkly::Client.new(sdk_key, config)

To learn more, read the API documentation.