LaunchDarkly is a feature management tool for software applications. It provides feature flags to the development teams to control their software product releases and their tests.
-
Testing code live in production
Teams can create groups of users according to their specific identifiers, such as their unique keys, their regions, users’ ages etc.
Test groups can also be created according to the users’ identifiers for testing purposes.
Even if teams don’t want to classify their users, they can deploy their tests to just some percentage of the users by enabling the feature flags to x% of users.
-
Feature release management
The new deployment, new feature or any additional thing on the software product can be controlled by a feature flag.
For example, a team wanted to create a new feature for users in a specific region, let’s say in the USA.
The thing that team needs to release their new feature in this country is creating a feature flag, which is a kind of a controller for the new feature. By creating rules for this feature flag through a simple UI, teams can adjust their targets for their new feature.
The benefits of Launchdarky do not end here. You can check their website and use cases for further information.
LaunchDarkly provides a Redis® integration to make teams able to have Redis-backed feature store. At that point, Serverless Redis® comes into play as an easy, fast and feasible option.
LaunchDarkly Setup
The first step is creating a personal or team account in LaunchDarkly
After signing in, we are going to create a feature flag, that we are going to use.
To keep things simple in this demo, I am going to create a feature flag with name “test” and this flag will return a boolean value. So, the variations of this flag will be true or false.
Now, if we would like to enable some specific users, we can add those users as targets for variations of the flag.
The users may also be the other development teams in the company. If one of the teams doesn’t want to affect some teams in the same company, then they can prevent them to have the new feature by returning false to those teams.
The other option is creating rules for return values of the feature flag. It is the same logic with an “if” statement.
The example rule in the screenshot above: If the country of the user is USA, then returns true (enable the user to receive that particular feature), else false.
There are lots of options to create rules.
The one way that I most loved to adjust the distribution of the flag was percentage rollout. By this option, we can return true to the specified percentage of the users, and false to others.
LaunchDarkly Java Client Example
In this blog, we are going to work on the server side. The demo endpoint is very simple. If the feature flag is false, then return false, else true.
We are going to follow the instructions on LaunchDarkly docs.
First, we need to install the LaunchDarkly SDK as a dependency.
<dependency>
<groupId>com.launchdarkly</groupId>
<artifactId>launchdarkly-java-server-sdk</artifactId>
<version>5.9.0</version>
</dependency>
// or in Gradle:
implementation group: 'com.launchdarkly', name: 'launchdarkly-java-server-sdk', version: '5.9.0'
<dependency>
<groupId>com.launchdarkly</groupId>
<artifactId>launchdarkly-java-server-sdk</artifactId>
<version>5.9.0</version>
</dependency>
// or in Gradle:
implementation group: 'com.launchdarkly', name: 'launchdarkly-java-server-sdk', version: '5.9.0'
After that, our LaunchDarkly Java client will be like below.
package com.example.demo;
import com.launchdarkly.sdk.server.Components;
import com.launchdarkly.sdk.server.LDClient;
import com.launchdarkly.sdk.server.LDConfig;
import com.launchdarkly.sdk.server.integrations.Redis;
import java.net.URI;
public class ClientSingleton {
private static ClientSingleton _clientSingleton_ = null;
private LDClient ldClient;
private ClientSingleton(){
ldClient = new LDClient("YOUR_SDK_KEY");
}
public static ClientSingleton getInstance(){
if (_clientSingleton_ == null){
_clientSingleton_ = new ClientSingleton();
}
return _clientSingleton_;
}
public static LDClient getClient(){
return getInstance().ldClient;
}
}
package com.example.demo;
import com.launchdarkly.sdk.server.Components;
import com.launchdarkly.sdk.server.LDClient;
import com.launchdarkly.sdk.server.LDConfig;
import com.launchdarkly.sdk.server.integrations.Redis;
import java.net.URI;
public class ClientSingleton {
private static ClientSingleton _clientSingleton_ = null;
private LDClient ldClient;
private ClientSingleton(){
ldClient = new LDClient("YOUR_SDK_KEY");
}
public static ClientSingleton getInstance(){
if (_clientSingleton_ == null){
_clientSingleton_ = new ClientSingleton();
}
return _clientSingleton_;
}
public static LDClient getClient(){
return getInstance().ldClient;
}
}
The reason I created LaunchDarkly Java client like this is the warning in their docs.
In this blog, I created my API endpoint by using Spring which I feel comfortable with.
Here is the simple endpoint:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.launchdarkly.sdk.*;
import com.launchdarkly.sdk.server.*;
import java.io.IOException;
import java.net.URI;
@RestController
public class test {
@GetMapping("/")
public static String getVar() throws IOException {
LDClient ldClient = ClientSingleton.getClient();
// Set up the user properties. This user should appear on your
// LaunchDarkly users dashboard soon after you run the demo.
LDUser user = new LDUser.Builder("unique id").build();
boolean showFeature = ldClient.boolVariation("test", user, false);
System.out.println("SDK successfully connected! The value of test is " + showFeature + " for " + user); ldClient.close();
if(showFeature){
return "test feature is enabled for us :) ";
} else{
return "test feature is disabled for us :( ";
}
}
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.launchdarkly.sdk.*;
import com.launchdarkly.sdk.server.*;
import java.io.IOException;
import java.net.URI;
@RestController
public class test {
@GetMapping("/")
public static String getVar() throws IOException {
LDClient ldClient = ClientSingleton.getClient();
// Set up the user properties. This user should appear on your
// LaunchDarkly users dashboard soon after you run the demo.
LDUser user = new LDUser.Builder("unique id").build();
boolean showFeature = ldClient.boolVariation("test", user, false);
System.out.println("SDK successfully connected! The value of test is " + showFeature + " for " + user); ldClient.close();
if(showFeature){
return "test feature is enabled for us :) ";
} else{
return "test feature is disabled for us :( ";
}
}
}
LaunchDarkly – Upstash Redis® Integration
Storing our feature flag in Redis is possible with LaunchDarkly. At that point, serverless Redis can be used as our Redis datastore for our LaunchDarkly client.
We are following the Upstash docs first, if we don’t have a Redis database yet.
Then, to connect our serverless Redis to the LaunchDarkly client, first we need to install the LaunchDarkly Java Redis library, as it is stated in their library.
<dependency>
<groupId>com.launchdarkly</groupId>
<artifactId>launchdarkly-java-server-sdk-redis-store</artifactId>
<version>XXX</version>
</dependency>
<dependency>
<groupId>com.launchdarkly</groupId>
<artifactId>launchdarkly-java-server-sdk-redis-store</artifactId>
<version>XXX</version>
</dependency>
After having the dependency, we can connect our serverless Redis by using LaunchDarkly Redis integration. To do that, we need to import it.
import com.launchdarkly.sdk.server.*;
import com.launchdarkly.sdk.server.integrations.*;
import com.launchdarkly.sdk.server.*;
import com.launchdarkly.sdk.server.integrations.*;
Then, we can connect it by adding configuration to the client as follows.
LDConfig config = new LDConfig.Builder().dataStore(
Components.persistentDataStore(
Redis.dataStore().uri(
URI.create("redis://:<REDIS-PASSWORD>@<REDIS-ENDPOINT>:<PORT>")
)
).cacheSeconds(30)
)
.build();
ldClient = new LDClient("YOUR_SDK_KEY", config);
LDConfig config = new LDConfig.Builder().dataStore(
Components.persistentDataStore(
Redis.dataStore().uri(
URI.create("redis://:<REDIS-PASSWORD>@<REDIS-ENDPOINT>:<PORT>")
)
).cacheSeconds(30)
)
.build();
ldClient = new LDClient("YOUR_SDK_KEY", config);
When we check our Upstash Redis by using the “Data Browser” tab in the console, we can see the following data.
Conclusion
LaunchDarkly is helping companies to manage their rollouts and deployments by providing feature flags.
In this blog post, we have utilized feature flags from LaunchDarkly and stored them in Upstash Redis by using the LaunchDarkly Redis integration.
Since this one was just an example demonstrates the integration, the functionality was very basic. LaunchDarkly can be used in so many ways and serverless Redis is ready to store flags.