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

EDIT ON GITHUB

Using Redis as a persistent feature store

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

Overview

This topic explains how to use the SDK Redis integration as a persistent feature store.

Many of our server-side SDKs support Redis. The available options are slightly different in each language, but you can always specify the following:

  • The Redis host address (defaults to localhost:6379)
  • A prefix string to add to all keys used by the store, to avoid collisions in case the database is also being used for some other purpose
  • The length of time that recently read or updated data should be cached in memory
Supported Redis configurations

The LaunchDarkly SDKs use third-party open-source libraries to connect to Redis. Not all of these have the same level of support for advanced Redis configurations. Specifically, most of the SDKs and the Relay Proxy do not support connecting to a Redis cluster or using Redis Sentinel for service discovery.

To learn more, read the documentation for the individual SDKs below, or their Redis integration add-on libraries for SDKs that do not have this integration built in.

How the SDKs store data in Redis

The Redis integrations for all LaunchDarkly server-side SDKs use the same conventions, so that SDK instances and Relay Proxy instances sharing a single Redis store can interoperate correctly.

The storage schema is as follows:

  • There is always a "prefix" string that provides a namespace for the overall data set. If you do not specify a prefix in your configuration, it is launchdarkly.
  • For each type of data that the SDK can store, there is a hash whose key is PREFIX:TYPE. PREFIX is the configured prefix string. TYPE denotes the type of data such as features and segments.
  • Within each hash, there is one field per data item. For instance, the hash PREFIX:features has one field per feature flag. The field name is the unique key of the item, such as the flag key for a feature flag, and the value is a serialized representation of that item, in a format that is determined by the SDK.
  • An additional key, PREFIX:$inited, is created with an arbitrary value when the SDK stores a full set of feature flag data. This allows a new SDK instance to check whether there is already a valid data set that was stored earlier.
  • The SDK may use additional keys starting with the PREFIX string, so you should not assume that the TYPE values mentioned above and $inited are the only possible keys. The SDK never adds, modifies, or removes any keys in Redis other than ones starting with the PREFIX, so it is safe to share a Redis instance that is also being used for other purposes.

Server-side SDKs

In the following examples, the Redis feature store is set to use a host address of my-redis:6379, a prefix string of "my-key-prefix", and a cache TTL of 30 seconds.

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

.NET

To use Redis with the .NET SDK you must install an additional package named LaunchDarkly.ServerSdk.Redis.

1using LaunchDarkly.Sdk.Server;
2using LaunchDarkly.Sdk.Server.Integrations;
3var config = Configuration.Builder(sdkKey)
4 .DataStore(
5 Components.PersistentDataStore(
6 Redis.DataStore()
7 .HostAndPort("my-redis", 6379)
8 .Prefix("my-key-prefix")
9 ).CacheSeconds(30)
10 )
11 .Build();
12var client = new LDClient(config);
13
14
15// Before version 6.0, the syntax was different:
16
17using LaunchDarkly.Client;
18using LaunchDarkly.Client.Redis;
19
20var store = RedisComponents.RedisFeatureStore()
21 .WithRedisHostAndPort("my-redis", 6379)
22 .WithPrefix("my-key-prefix")
23 .WithCacheExpiration(TimeSpan.FromSeconds(30));
24
25var config = Configuration.Default(sdkKey)
26 .WithFeatureStoreFactory(store);
27var client = new LDClient(config);

To learn more, read dotnet-server-sdk-redis.

C/C++ (server-side)

The C/C++ integration is part of the main SDK distribution.

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

Erlang

1LdOptions = #{
2 redis_host => "redis",
3 redis_port => "6379",
4 redis_prefix => "default",
5 feature_store => ldclient_storage_redis
6},
7ldclient:start_instance("your_sdk_key", LdOptions).

Go

The Go integration is in github.com/launchdarkly/go-server-sdk-redis for 5.0.0 or higher of the SDK. In earlier SDK versions, it is in the main SDK distribution as the subpackage redis.

1import (
2 ld "gopkg.in/launchdarkly/go-server-sdk.v5"
3 "gopkg.in/launchdarkly/go-server-sdk.v5/ldcomponents"
4 ldredis "github.com/launchdarkly/go-server-sdk-redis"
5)
6
7var config ld.Config
8config.DataStore = ldcomponents.PersistentDataStore(
9 ldredis.DataStore().
10 HostAndPort("my-redis", 6379).
11 Prefix("my-key-prefix"),
12).CacheSeconds(30)
13client := ld.MakeCustomClient(sdkKey, config, waitTime)
14
15
16// Before version 5.0, the syntax was different:
17import (
18 ld "gopkg.in/launchdarkly/go-server-sdk.v4"
19 ldredis "gopkg.in/launchdarkly/go-server-sdk.v4/redis"
20)
21
22factory, err := ldredis.NewRedisFeatureStoreWithDefaults(
23 ldredis.HostAndPort("my-redis", 6379),
24 ldredis.Prefix("my-key-prefix"),
25 ldredis.CacheTTL(30 * time.Second))
26config := ld.DefaultConfig
27config.FeatureStoreFactory = factory
28client := ld.MakeCustomClient(sdkKey, config, waitTime)

To learn more, read go-server-sdk-redis.

Haskell

If using the Haskell SDK you must install an additional package named launchdarkly-server-sdk-redis.

1import qualified Database.Redis as R
2import LaunchDarkly.Server
3import LaunchDarkly.Server.Store.Redis
4
5main = do
6 con <- R.checkedConnect R.defaultConnectInfo { R.connectHost = "my-redis:6379" }
7 backend <- makeRedisStore $ redisConfigSetNamespace "my-key-prefix" $ makeRedisStoreConfig con
8
9 let config = configSetStoreBackend backend $ makeConfig "your_sdk_key"
10
11 client <- makeClient config

Java

In the Java SDK 5.0 and later, you must install the additional package com.launchdarkly.launchdarkly-java-server-sdk-redis-store. In Java SDK 4.x and earlier, this integration is part of the main SDK distribution.

1import com.launchdarkly.sdk.server.*;
2import com.launchdarkly.sdk.server.integrations.*;
3
4LDConfig config = new LDConfig.Builder()
5 .dataStore(
6 Components.persistentDataStore(
7 Redis.dataStore().uri(URI.create("redis://my-redis:6379"))
8 .prefix("my-key-prefix")
9 ).cacheSeconds(30)
10 )
11 .build();
12LDClient client = new LDClient(sdkKey, config);
13
14
15// Before version 5.0, the syntax was different:
16import com.launchdarkly.client.*;
17
18LDConfig config = new LDConfig.Builder()
19 .featureStoreFactory(
20 Components.redisFeatureStore(URI.create("redis://my-redis:6379"))
21 .prefix("my-key-prefix")
22 .cacheTime(30, TimeUnit.SECONDS)
23 )
24 .build();

To learn more, read java-server-sdk-redis.

Lua

1local l = require("launchdarkly_server_sdk")
2local r = require("launchdarkly_server_sdk_redis")
3
4local backend = r.makeStore({
5 host = "my-redis",
6 port = 6379,
7 prefix = "my-key-prefix"
8})
9
10local c = l.clientInit({
11 key = "your_sdk_key",
12 featureStoreBackend = backend
13)}

Node.js (server-side)

In version 6.0.0 and higher of the Node.js SDK, you must install the additional package launchdarkly-node-server-sdk-redis. In Node.js SDK 5.x and earlier, this integration is part of the main SDK distribution.

1const LaunchDarkly = require('launchdarkly-node-server-sdk');
2const RedisFeatureStore = require('launchdarkly-node-server-sdk-redis');
3
4const redisOpts = {
5 url: 'redis://my-redis:6379'
6};
7const store = RedisFeatureStore(redisOpts, 30, 'my-key-prefix');
8
9const config = {
10 featureStore: store
11};
12const client = LaunchDarkly.init(sdkKey, config);

PHP

The PHP integration is part of the main SDK distribution, but you must also must install the package predis/predis.

1/*
2 There is no parameter for the cache TTL. The PHP SDK does not cache
3 data from Redis, since in PHP the entire in-memory application state is
4 normally discarded after each request.
5*/
6$fr = LaunchDarkly\Integrations\Redis::featureRequester([
7 'redis_host' => 'my-redis',
8 'redis_port' => 6379,
9 'redis_prefix' => 'my-key-prefix'
10]);
11$client = new LaunchDarkly\LDClient("your_sdk_key", [
12 'feature_requester' => $fr
13]);
14
15// Prior to version 3.5.0, use this syntax:
16// $client = new LaunchDarkly\LDClient("your_sdk_key", [
17// 'feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester',
18// 'redis_host' => 'my-redis',
19// 'redis_port' => 6379,
20// 'redis_prefix' => 'my-key-prefix'
21// ]);

Python

The Python integration is part of the main SDK distribution, but you must also install the package redis.

1import ldclient
2from ldclient.config import Config
3from ldclient.feature_store import CacheConfig
4from ldclient.integrations import Redis
5
6store = Redis.new_feature_store(url='redis://my-redis:6379',
7 prefix='my-key-prefix', caching=CacheConfig(expiration=30))
8
9# Prior to version 6.7.0, use this syntax:
10# store = RedisFeatureStore(url='redis://my-redis:6379', prefix='my-key-prefix',
11# expiration=30)
12
13config = Config(feature_store=store)
14ldclient.set_config(config)

Ruby

The Ruby integration is part of the main SDK distribution, but you must also install the gems redis and connection_pool.

1require 'ldclient-rb'
2
3store = LaunchDarkly::Integrations::Redis.new_feature_store(
4 redis_url: 'redis://my-redis:6379',
5 prefix: 'my-key-prefix',
6 expiration: 30
7)
8
9# Prior to version 5.5.0, use "LaunchDarkly::RedisFeatureStore.new" instead
10# of "LaunchDarkly::Integrations::Redis.new_feature_store"
11
12config = LaunchDarkly::Config.new(
13 feature_store: store
14)
15client = LaunchDarkly::Client.new(sdk_key, config)