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

EDIT ON GITHUB

Using DynamoDB as a persistent feature store

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

Overview

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

Data size limit in DynamoDB

DynamoDB does not support storing values greater than 400KB (or slightly less, since that number includes the size of the column metadata). Therefore, using DynamoDB as a persistent feature store does not work if the JSON representation of any feature flag or user segment exceeds that size.

To see the JSON representations of all flags and segments, query https://app.launchdarkly.com/sdk/latest-all with your SDK key in the Authorization header.

Many of our server-side SDKs support DynamoDB. DynamoDB is a particularly useful solution if you are running code in AWS Lambda, since it can be accessed from Lambda without needing access to any VPC resource.

In your application code, the only required parameter is the table name, although you can also specify any other options supported by AWS. By default, the DynamoDB driver expects to get your AWS credentials and region from environment variables or local configuration files, as described in the AWS SDK documentation.

The table must already exist before your application starts. It must have a partition key called "namespace", and a sort key called "key". The SDK does not create the table automatically because it would not know what values to use for other properties such as permissions and throughput.

DynamoDB imposes a limit of 400KB on the total size of any database item. In this implementation, each feature flag or user segment is a single item, so the feature store is not able to persist any flag or segment whose JSON representation is larger than that limit.

How the SDKs store data in DynamoDB

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

The storage schema is as follows:

  • For each data item that the SDK can store, such as a feature flag, there is a single DynamoDB data item, with the following attributes:
    • namespace: a string value that denotes the type of data, such as features and segments. Or, if you have specified a prefix string, the namespace is set to PREFIX:TYPE where PREFIX is your configured prefix and TYPE is the type of data.
    • key: the unique key of the item (such as the flag key for a feature flag).
    • version: a number that the SDK uses to keep track of updates.
    • item: a serialized representation of the data item, in a format that is determined by the SDK.
  • An additional item with a namespace of $inited or PREFIX:$inited is created when the SDK has stored 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.
  • If you have specified a prefix string, the SDK never adds, modifies, or removes any items in the DynamoDB table that do not have a namespace starting with PREFIX:, so it is safe to share a DynamoDB table that is also being used for other purposes.

Server-side SDKs

In the following examples, the DynamoDB feature store is set to use a table called "my-table" and a cache TTL of 30 seconds. The DynamoDB feature store does support using a key prefix, as shown in the Redis examples, but it is uncommon for one DynamoDB table to be shared by multiple applications.

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

.NET

If using the .NET SDK, you must install the additional package LaunchDarkly.ServerSdk.DynamoDB.

1using LaunchDarkly.Sdk.Server;
2using LaunchDarkly.Sdk.Server.Integrations;
3var config = Configuration.Builder(sdkKey)
4 .DataStore(
5 Components.PersistentDataStore(
6 DynamoDB.DataStore("my-table")
7 ).CacheSeconds(30)
8 )
9 .Build();
10var client = new LDClient(config);
11
12
13// Before version 6.0, the syntax was different:
14
15using LaunchDarkly.Client;
16using LaunchDarkly.Client.DynamoDB;
17
18var store = DynamoDBComponents.DynamoDBFeatureStore("my-table")
19 .WithCaching(FeatureStoreCacheConfig.Enabled.WithTtlSeconds(30));
20
21var config = Configuration.Default(sdkKey)
22 .WithFeatureStoreFactory(store);
23var client = new LDClient(config);

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

Go

The Go integration is in github.com/launchdarkly/go-server-sdk-dynamodb for version 5.0.0 or higher of the SDK. In versions 4.5.1 and higher, but below 5.0.0, it is in the main SDK distribution as the subpackage lddynamodb.

1import (
2 ld "gopkg.in/launchdarkly/go-server-sdk.v5"
3 "gopkg.in/launchdarkly/go-server-sdk.v5/ldcomponents"
4 lddynamodb "github.com/launchdarkly/go-server-sdk-dynamodb"
5)
6
7var config ld.Config
8config.DataStore = ldcomponents.PersistentDataStore(
9 lddynamodb.DataStore("my-table"),
10).CacheSeconds(30)
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 "gopkg.in/launchdarkly/go-server-sdk.v4/lddynamodb"
18)
19
20factory, err := lddynamodb.NewDynamoDBFeatureStoreFactory("my-table",
21 lddynamodb.CacheTTL(30 * time.Second))
22config := ld.DefaultConfig
23config.FeatureStoreFactory = factory
24client := ld.MakeCustomClient(sdkKey, config, waitTime)

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

Java

If using the Java SDK, you must install the additional package com.launchdarkly.launchdarkly-java-server-sdk-dynamodb-store. You must also add software.amazon.awssdk.dynamodb if your application does not already use the AWS SDK.

1import com.launchdarkly.sdk.server.*;
2import com.launchdarkly.sdk.server.integrations.*;
3
4LDConfig config = new LDConfig.Builder()
5 .dataStore(
6 Components.persistentDataStore(
7 DynamoDb.dataStore("my-table")
8 ).cacheSeconds(30)
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.dynamodb.*;
17
18LDConfig config = new LDConfig.Builder()
19 .featureStoreFactory(
20 DynamoDbComponents.dynamoDbFeatureStore("my-table")
21 .caching(FeatureStoreCacheConfig.enabled().withTtlSeconds(30));
22 )
23 .build();

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

Node.js (server-side)

If using the Node.js SDK, you must install the additional package launchdarkly-node-server-sdk. As of the 2.0.0 release of that package, the aws-sdk package that it uses is not automatically loaded as a transitive dependency. This saves space when running in AWS Lambda, where aws-sdk is built in. If you are not running in Lambda, you must separately install aws-sdk.

1const LaunchDarkly = require('launchdarkly-node-server-sdk');
2const DynamoDBFeatureStore = require('launchdarkly-node-server-sdk-dynamodb');
3
4const store = DynamoDBFeatureStore('my-table', { cacheTTL: 30 });
5
6const config = {
7 featureStore: store
8};
9const client = LaunchDarkly.init(sdkKey, config);

PHP

The PHP integration is part of the main SDK distribution as of version 3.5.0, but you must also install the package aws/aws-sdk-php.

1/*
2 Note that there is no parameter for the cache TTL; the PHP SDK does not cache
3 data from DynamoDB, since in PHP the entire in-memory application state is
4 normally discarded after each request.
5*/
6$fr = LaunchDarkly\Integrations\DynamoDb::featureRequester([
7 'dynamodb_table' => 'my-table'
8]);
9$client = new LaunchDarkly\LDClient("your_sdk_key", [
10 'feature_requester' => $fr
11]);

Python

The Python integration is part of the main SDK distribution as of version 6.7.0, but you must also install the package boto3.

1import ldclient
2from ldclient.config import Config
3from ldclient.feature_store import CacheConfig
4from ldclient.integrations import DynamoDB
5
6store = DynamoDB.new_feature_store('my_table',
7 caching=CacheConfig(expiration=30))
8
9config = Config(feature_store=store)
10ldclient.set_config(config)

Ruby

The Ruby integration is part of the main SDK distribution as of version 5.1.1, but you must also install the gem aws-sdk-dynamodb.

1require 'ldclient-rb'
2
3store = LaunchDarkly::Integrations::DynamoDB.new_feature_store('my-table',
4 { expiration: 30 })
5
6config = LaunchDarkly::Config.new(
7 feature_store: store
8)
9client = LaunchDarkly::Client.new(sdk_key, config)