5 Best Practices for Getting Started with LaunchDarkly featured image

When implementing or adopting a new technology, there always comes a time when we shift out of the research phase and set the wheels of change in motion. You know the what and the why of your new solution, but now comes the hardest part – the how. Feature management is no different. You've done the research, reading articles like The Five Stages of Feature Flag Adoption or Why Decouple Deployments from Releases and know that LaunchDarkly is the right tool for your organization, but how do you get started? That’s the question we’ll answer for you here. Here are five best practices for getting started with LaunchDarkly.

1. Set up Your Project

If you haven’t done so already, sign up for a LaunchDarkly account. If you’re not a LaunchDarkly customer, you can create an account with our 14-day free trial. Once you have an account ready to go, it’s time to start configuring your first project. 

Projects

The hierarchy of LaunchDarkly is this – A LaunchDarkly organization contains all of that organization’s LaunchDarkly projects, which are composed of LaunchDarkly environments. Think of the project as either your whole application or a dedicated component within your application, e.g., say you and your team are managing a web store application, you could have a project called Web Store which will contain all your feature flags for that application.

By default, LaunchDarkly provides you with a project called LaunchDarkly which you can use to get started with or you can create a new one. To do this, you go to the Account Settings tab within LaunchDarkly, select Projects, and then create project, as shown below:

Process for creating new project in LaunchDarkly

Process for creating new project in LaunchDarkly

The best way to create and manage projects is by aligning them to anything that could be considered a single product by your end users, e.g., a web application, a mobile application, a back-end service, etc. The reason for this is that flags created are shared across the entire project. From an organizational standpoint, it’s best if those flags all support the same thing.

Environments

If projects represent your applications as a whole, environments represent the release stages of that application. Think about the series of stages that your software releases typically go through: development, QA, testing, staging, production, etc. LaunchDarkly environments allow you to replicate your software release stages so you can manage releases through the entire lifecycle. Projects can contain multiple environments and each environment uses different server-side, client-side, and mobile SDK keys. As flags are changed to serve different variations, those variations only get served to applications connected to LaunchDarkly with the specified environment keys.

Example of multiple environments within a LaunchDarkly project

Example of multiple environments within a LaunchDarkly project

It’s important to keep track of where various features are in the release lifecycle. LaunchDarkly release pipelines let you create an aggregated view of your environments and monitor the status of each feature as it moves from stage to state. Having this type of insight can be especially important as you start to add more users to your projects.

Example of a release pipeline in LaunchDarkly

Example of a release pipeline in LaunchDarkly

2. Choose Your SDK

Now that we have our projects and environments ready to go, it’s time to connect our application to LaunchDarkly. LaunchDarkly supports over 25 different SDKs, meaning we can support whatever language you are programming in. Let’s walk through the steps for initializing a LaunchDarkly SDK.

Get your SDK Keys

As mentioned earlier, each LaunchDarkly environment has its own unique set of SDK keys. Let’s quickly walk through the different keys and how they are used:

  • Server-side - Backend, multi-user systems, like web servers. Intended for secure environments.
  • Client-side - Designed for single users (e.g. mobile devices, browser sessions, etc.) and edge use cases. Not expected to be used in as secure an environment as server-side SDKs. 
  • Mobile SDK key - Similar to client-side, but also includes multi-environment support and handles the polling/streaming connection with LaunchDarkly slightly differently. 

It’s important to choose the correct key for the SDK that you intend to use. Typically, problems with initializing the SDK or connecting to LaunchDarkly can be traced back to the wrong SDK key being used. To get these values you can choose one of two paths: 

  1. Retrieve from Account Setting - As we showed above, the SDK keys are available in the projects screen. Go to that tab, select the project and environment that you want the keys for. 
  2. Use the shortcut cmd+k or ctrl+k in your LaunchDarkly environment or click on the search bar at the top of the page and type in: “copy SDK key for current environment”.

Getting SDK key

Once you have the correct key values, you’re ready to initialize your SDK.

Installing and initializing LaunchDarkly SDK

Each LaunchDarkly SDK follows the same pattern for initializing an SDK. First, you import/install the required SDK package into your application environment and then you configure it within your application using the SDK keys you retrieved. We’re doing two primary things when we initialize the SDK. First we import the SDK that we just installed then we run an initialization command to connect to LaunchDarkly. 

Here are a couple of examples using some of our most popular frameworks:

Javascript SDK

Step 1: Installation 
Install the SDK using a package manager, like npm, yarn, or bower:

npm install lauchdarkly-js-client-sdk

Step 2: Setup client initialization, will look something like this:

import * as LaunchDarkly from "launchdarkly-js-client-sdk"

const context = {
	kind: "user",
	key: "context-key-123abc",
	name: "anonymous"
};

const client = LaunchDarkly.initialize("<add your client-side key as an env variable>", context);
Python SDK

Step 1: Install the correct SDK package:
Install the SDK using a package manager, like pip:

pip install launchdarkly-server-sdk

Step 2: Setup client initialization, will look something like this:

import os
import ldclient
from ldclient.config import Config

# Set sdk_key to your LaunchDarkly SDK key before running
sdk_key = os.getenv("LAUNCHDARKLY_SERVER_KEY")

if __name__ == "__main__":
	if not sdk_key:
    	show_message("Please set the LAUNCHDARKLY_SERVER_KEY env first")
    	exit()

	ldclient.set_config(Config(sdk_key))

	# The SDK starts up the first time ldclient.get() is called
	if ldclient.get().is_initialized():
    	show_message("SDK successfully initialized!")
	else:
    	show_message("SDK failed to initialize")
        exit()

	# Set up the evaluation context. This context should appear on your
	# LaunchDarkly contexts dashboard soon after you run the demo.
	context = Context.builder('example-user-key').name('Sandy').build()
React Web SDK (Typescript on Next.js)

Quick note, this is showing the configuration of a Next.js React project. Because Next assumes that all components should be rendered server side, there are some additional configurations required. We need to make sure that LaunchDarkly is treated as a client-side component in order to receive and process real time updates. React has a number of different configurations, so be sure to read the SDK documentation for your specific setup

Step 1: Install the correct SDK package:
Install the SDK using a package manager, like npm, yarn, or bower:

npm install launchdark-react-client-sdk

Step 2: Initialize the SDK in a React component

//component file, named like LDProvider.tsx 
"use client";

import { use } from "react";
import { asyncWithLDProvider } from "launchdarkly-react-client-sdk";

export default function AsyncLDProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  const LDDynaProvider = use(
	asyncWithLDProvider({
  	clientSideID: process.env.NEXT_PUBLIC_LD_CLIENT_SDK_KEY || '',
  	reactOptions: {
    	useCamelCaseFlagKeys: false
  	},
  	context: {
    	kind: "user",
    	key: "1",
    	name: "Anonymous",
  	},
	})
  );

  return <LDDynaProvider>{children}</LDDynaProvider>;
}

Step 3: Wrap your application with the Provider component

//in your layout.tsx file
import dynamic from "next/dynamic";
import { Suspense } from "react";

const AsyncLDProvider = dynamic(() => import("@/components/ldprovider"), {
  ssr: false,
});

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
	<html lang="en">
  	<body className={inter.className}>
    	<Suspense fallback={<div>Loading...</div>}>
      	<AsyncLDProvider>{children}</AsyncLDProvider>
    	</Suspense>
  	</body>
	</html>
  );
}
iOS SDK

Step 1: Install the SDK with Swift Package Manager, CacaoPods, Carthage and add it to the coordinating configuration file, here’s the example using Package.swift:

//place in your Package.swift file 
   dependencies: [
       .package(url: "https://github.com/launchdarkly/ios-client-sdk.git", .upToNextMinor("9.0.0")),
   ],
   targets: [
       .target(
           name: "YOUR_TARGET",
           dependencies: ["LaunchDarkly"]
       )
   ],
//... 

Step 2: Initialize the SDK in your application

let config = LDConfig(mobileKey: "mobile-key-123abc", autoEnvAttributes: .enabled)
let context  = LDContextBuilder(key: "context-key-123abc")
context.trySetValue("name", .string("Sandy"))
context.trySetValue("email", .string("sandy@example.com"))

LDClient.start(config: config, context: context, startWaitSeconds: 5) { timedOut in
	if timedOut {
    	// Client may not have the most recent flags for the configured context
	} else {
    	// Client has received flags for the configured context
	}
}

These are just a handful of examples of how you can initialize a LaunchDarkly SDK, but they all follow the same core structure. Install the SDK package into your application environment, initialize the SDK to establish a connection, start using LaunchDarkly within the app. Once the SDK has been initialized, you’ll be able to evaluate flag values, send custom events from the app to LaunchDarkly, identify and update custom contexts, and so much more. For more information about initializing a specific SDK, visit the SDK documentation.

3. Create Your First Flag

Now that you’ve set up your project and enabled your application to communicate with LaunchDarkly, you’re ready to start feature flagging! As mentioned in our Five Stages of Feature Flag Adoption article, most organizations will start with boolean flags – determining which code is served to a user based on a true or false value. Starting with boolean flags is foundational to understanding the power of a feature management platform not only because it provides immediate value, but it’s also the least intrusive on your development workflow. For example, here’s what a boolean flag evaluation looks like on a Node.js server for evaluating different API routes:

// initializing the client
const client = ld.init(process.env.SDK_KEY, context);

app.get('/api', async (req, res) => {
  // evaluate the flag and store value in a variable, in this case called newRoute 
  const newRoute = await client.variation('new-route-flag-key', false);
  
  //run an if/else statement based on value of newRoute
  if (newRoute) {
    try {
      //new API route logic
    } catch (e) {
      console.error(error.message);
    }
  } else {
    try {
      //old API route logic 
    } catch (e) {
      console.error(error.message);
    }
  }
});

If you’ve used if/else logic in your code before, then you’re ready to start writing feature flags into your code. But with LaunchDarkly there is so much more that can be done beyond the boolean flag. LaunchDarkly supports multiple variation types including boolean, strings, numbers, and JSON objects. Using non-boolean flags enables the user to create multivariate flags. Multivariate flags are flags that can serve more than two variations and are great for passing in dynamic values or running experiments. Here’s an example code block where we are using a multivariate flag to determine which image gallery to display based on the user’s region in a React application:

// In react we use a useFlags() hook instead of the .variation function, 
// it's unique to React, but functionally serves the same purpose, 
// we're just using the hook to evaluate the flag key region 
const {region} = useFlags();

// Depending on the value returned from region, we render didn't image galleries. 
// code for mountain west 
if (region == "mountainWest") {
  return (
    <Box sx={{ width: 900, height: 300, overflowY: 'scroll' }}>
      <ImageList variant="masonry" cols={5} gap={8}>
        {mountainWest.map((item) => (
          <ImageListItem key={item.img}>
            <img
              src={`${item.img}?w=248&fit=crop&auto=format`}
              srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`}
              alt={item.title}
              loading="lazy"
            />
          </ImageListItem>
        ))}
      </ImageList>
    </Box>
  );
}

//code for pacific northwest
if (region == "pacificNorthwest") {
  return (
    <Box sx={{ width: 900, height: 300, overflowY: 'scroll' }}>
      <ImageList variant="masonry" cols={5} gap={8}>
        {pacificNorthwest.map((item) => (
          <ImageListItem key={item.img}>
            <img
              src={`${item.img}?w=248&fit=crop&auto=format`}
              srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`}
              alt={item.title}
              loading="lazy"
            />
          </ImageListItem>
        ))}
      </ImageList>
    </Box>
  );
}

// code for the west coast
if (region == "westCoast") {
  return (
    <Box sx={{ width: 900, height: 300, overflowY: 'scroll' }}>
      <ImageList variant="masonry" cols={5} gap={8}>
        {westCoast.map((item) => (
          <ImageListItem key={item.img}>
            <img
              src={`${item.img}?w=248&fit=crop&auto=format`}
              srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`}
              alt={item.title}
              loading="lazy"
            />
          </ImageListItem>
        ))}
      </ImageList>
    </Box>
  );
}

The code block is a little lengthy, but essentially we’re just rendering different image galleries based on the string value returned from our region flag. 

4. Expanding Flag Usage

Now that you’ve gotten your first feature flagged with a boolean flag or multivariate flag, you’re ready to start expanding your use cases with feature flags. The process of implementing them in code is going to be the same, but the purpose behind the flag can be very different. Fortunately, LaunchDarkly knows this and tries to provide you with some guidance for how different flags should be used, we call these flag templates. 

Flag templates are predefined configurations for various uses of LaunchDarkly feature flags. The default templates include:

  • Release Flags - temporary flags used for releasing new features. This template defaults to a boolean and automatically switches the default rule to serve the “off” variation. 
  • Kill Switch Flags - permanent flags used for managing application wide functionality, ex: maintenance modes or third-party integrations. This template also defaults to a boolean, but does not change the default rule. 
  • Experiment Flags - temporary flag used for running LaunchDarkly experiments against new features. Defaults to a string flag with three variations: control, variation A, and variation B. 
  • Migration Flags - A unique temporary flag that is used for managing database migrations with LaunchDarkly. Offers two, four, and six stage migrations paths, for a deeper dive on migration flags, read this article
  • Custom Flag Templates - None of these other templates seem to be exactly right? Customize your own flag template and save it for future use! 

Each of these templates have a default starting point, but they are all customizable and can be saved for future use. If there’s a specific pattern without your application that you want to enforce, then using custom templates is probably the best option for your organization.

5. Set Up Access Controls

Let’s recap, we’ve set up our project, selected our SDKs, implemented our first feature flags, and started to expand how we use feature flags in our application. At this point, you’re probably ready to let the rest of the team have access to your project. This leads us to our final best practice, setting up access controls for your LaunchDarkly project. LaunchDarkly is a collaborative tool, but you still want to make sure you’re enforcing the right permissions and ensuring that only the right users are accessing the right environments/flags. Fortunately, LaunchDarkly is designed for teams of all sizes and offers granular access controls.

User Roles

By default, LaunchDarkly supports four different types of user roles: 

  • Owners - The one who created the LaunchDarkly organization or has been delegated the ownership role by a previous owner. This user has complete control over the entire LaunchDarkly organization including projects, environments, billing, etc. There is only one per organization. 
  • Administrators - Similar to owners in that they can do just about anything, except for changing whoever has the owner role. You can have multiple administrators in an account.  
  • Writers - Can create and modify LaunchDarkly flags, projects, and environments, but has no control over administrative tasks like billing or managing account members.  
  • Readers - Can view any information, but cannot make changes. Good for users that need to access LaunchDarkly for information, but do not need the ability to change things. 

Any member that is added to a LaunchDarkly organization is assigned one of these roles. However, you are not limited to only these four. LaunchDarkly also supports the ability to create custom roles which give you the ability to make a user's capabilities as broad or as narrow as is required. Custom roles can be applied to specific individuals or across entire teams.

Teams

LaunchDarkly teams are how you group together users and manage their access across projects, environments, and even individual flags. You can use teams to organize end users and apply team-wide custom roles that can be as broad or as granular as you want. For example, say you want to give a team access to flags within a given project, but restrict their ability to manage your user segments. This could be because you’re using a third party tool for importing segment data or maybe you want a specific user managing those end user groups. Regardless the reason, you can apply a team wide policy that restricts access to all segments like this:

null

A custom role that allows access to feature flags, but not segments in the toggle-store project

In this policy, team members would be able to create, change, and delete flags, but could not do anything with the segments in that project. These roles can be applied to individual flags or individual actions as well.

Conclusion

We’ve only scratched the surface of what you can do with LaunchDarkly. LaunchDarkly targeting lets you control the impact radius of your releases and create personalized experiences for your users based on things like entitlements. Use LaunchDarkly as part of your next database migration ensuring a smooth transition to new systems. LaunchDarkly experimentation helps you validate the efficacy of your releases by measuring their impacts based on business metrics. LaunchDarkly can even help you instantly remediate issues through kill switches, flag triggers and integrations with various application performance monitoring (APM) tools. Now that you’re up and running with your own LaunchDarkly project, you can pick and choose which one of these use cases to explore next.

Related Content

More about Featured Collection

March 29, 2024