20 Oct 2017

Keeping Client-Side Feature Flags Secure

LaunchDarkly’s JavaScript SDK allows you to access feature flags in your client-side JavaScript. If you’re familiar with our server-side SDKs, setup for our JS SDK looks superficially similar—you can install the SDK via npm, yarn, or via CDN and be up and running with a few lines of code. However, if you dig a bit deeper into the source code and do an apples-to-apples comparison with our node SDK, you’ll see that our client-side SDK works completely differently under the hood.

There’s one simple reason for this difference—security. Because browsers are an untrusted environment, our client-side SDK uses a completely different approach that allows us to serve feature flags to your users securely. While we’ve made our approach as secure as possible out of the box, there are three best practices that we recommend all companies follow to maximize security when using client-side feature flags.

1. Choose Appropriate Use Cases

First, in a browser environment your entire JavaScript source code is fully exposed to the public. It may be minified and obfuscated, but obfuscation is not security. This means that if you’re using client-side feature flags, you must be aware that anyone can modify your source code directly and bypass your feature flags. For example, if you have a code snippet like this:

You can expect that any of your end users could inline edit the above code snippet in their browser window to show the brand new feature, bypassing the feature flag and its rollout rules entirely. This is a fact about how client-side feature flags work—not a limitation in the LaunchDarkly platform.

This doesn’t mean that client-side feature flags are always a security vulnerability—it just means that there are some use cases where a client-side feature flag alone isn’t appropriate. For example:

  • Launching a feature that is press-, publicity-, or competitor- sensitive. In this situation, having a user enable the feature early could derail a launch, or tip your company’s hand. Even the feature flag key itself (e.g. brand.new.feature) could be sensitive. In this scenario, you can’t even afford to push the new front-end code to production prior to launch, even if it’s kept dark.
  • Entitlements. A client-side feature flag alone is not a sufficient control for locking users out of functionality that they shouldn’t be able to access. In this case, a client-side feature flag is fine assuming it’s coupled to a backend feature flag. For example, you can use the same feature flag (with the same rollout rules) on both the front-end (to disable a UI element) and the back-end (to control access to a REST endpoint triggered by that same UI element).

Using client-side feature flags securely starts with choosing appropriate use cases. Ultimately, the choice depends on whether or not you can expose your new feature’s code to users that may not have the feature enabled.

2. Enable Secure Mode to Protect Customer Data

There’s a corollary to the observation that all JS code is fully exposed to the public—there is no way to securely pass authentication credentials to a 3rd party API from the front-end alone. Because anyone can view source, any API key or token that you pass to a 3rd party API via client-side JS is immediately exposed to users.

One solution to this problem is to sign requests—use a shared secret on the server-side to sign the data being passed to the 3rd party API to ensure that the data hasn’t been tampered with, or the request hasn’t been forged. Tools like Intercom take this approach. In Intercom’s case, request signing guarantees that a user can’t fetch chat conversations for a different user.

LaunchDarkly follows this approach as well. We call this Secure Mode, and when enabled, it guarantees that a user can’t impersonate another user and fetch their feature flag settings. Our server-side SDKs work in tandem with our client-side JavaScript SDK to make Secure Mode easy to implement. We recommend that all customers enable Secure Mode in their production environments.

3. Use a Package Manager to Bundle the SDK

There’s another aspect of security that comes with using any 3rd party service in your JavaScript—protecting yourself in case that service is attacked. Our recommended best practice is to embed our SDK in your code using a package manager, rather than injecting the SDK via script tag. We offer easy installation with popular package managers like npm, yarn, and bower. This does put the onus on you to upgrade when we release new versions of our SDK, but at the same time it can reduce latency to fetch the SDK and give you control in accepting updates.


We go to great lengths to ensure the security of our customers and their end users. We follow industry best practices in the operation of our service (we recently completed our SOC2 certification) in addition to providing advanced security controls in our product such as multi-factor authentication, scoped API access tokens, and role-based access controls. This approach to security extends to our client-side JavaScript SDK. By following the practices outlined here, you can ensure that your use of client-side feature flags keeps your data and your customers’ data safe.

13 Oct 2015

Launched: Account Permissions

We’ve just launched account permissions! Team members can now be assigned more restrictive roles on your team management page. There are several roles:

  • Readers— readers can see anything in LaunchDarkly, but can’t modify any data. This role is perfect for members of your organization that need visibility into your feature flags, but shouldn’t be able to modify rollout rules, or administer the system.
  • Writers— writers can modify feature flags, goals, environments and more. They can’t add new team members to the account, or manage your payment method or plans.
  • Admins / owners— admins and owners can do pretty much everything on the site. Owners can’t be removed from the account.

Account Permissions

Over time, we’ll be making our permissions model more powerful. It’ll be possible to put even finer-grained controls on your users, so you can lock down your production environment, or restrict your Test environment to QA engineers if necessary.

02 Oct 2015

Launched: Flag Status Indicators

LaunchDarkly now provides live status indicators for your feature flags. Our dashboard shows you which flags are active, which are candidates to be removed from your code, and which have already been deleted from your code, and are safe to remove from our dashboard.


This is the first of many new features we’re building to help developers manage feature flags throughout their development process. Cleaning up feature flags is an essential part of the development workflow, and LaunchDarkly is taking steps to make this as easy as possible. Happy launching!

02 Sep 2015

Launched: .NET support

LaunchDarkly now supports .NET!

We’ve just released the first supported version of our .NET SDK. Like all our other SDKs (we support Ruby, Python, Node.js, Java, Go, and more), it’s open source— check out the code on GitHub. We’ve also published a brand new .NET reference guide to help you dig in and integrate LaunchDarkly into your .NET application today.

Happy launching!

LaunchDarkly helps you build better software faster with feature flags as a service. Start your free trial now.
05 Aug 2015

Can we stop pretending that Docker is great for development environments?

tl;dr: It makes perfect sense to run backing services (databases, caching, storage, etc.) in Docker, but if you use a compiled language, Docker’s not the way to go for local development.

Every six months I try to use Docker for local development. I tried again recently, and found (once again) that the technology still isn’t ready. But this go-around I reached a further conclusion— for most development stacks, running Docker for local development is a pointless exercise. It introduces complexity and provides almost no benefits.

The crux of the problem is this: achieving an efficient edit, compile, run cycle means that your development container will not be the same as your production container. This negates one of the primary advantages of using containers. Furthermore, you will never make your edit, compile, run cycle as efficient or foolproof as running locally without a container. This means that you’re paying a containerization tax and reaping none of the rewards.

Let’s first look at my claim that an efficient edit, compile, run cycle requires separate “non-production” container definitions. First, assume otherwise. If you’re using your production container for development, your container must contain a pre-compiled artifact of some kind, or you’re doing something crazy like running the compilation in your Dockerfile. In either case, you need to re-build your container every time you make a change. Your E/C/R cycle looks something like this:

We went down this path, and found that the cycle took long enough (> 30 seconds, excluding the build time for the service itself) to trigger a boredom-induced context switch. This is a productivity killer.

You can argue that this is an implementation critique, and that (eventually) this cycle will be much faster, but to compete against local development, the build /restart steps need to be nearly free. They’re not, and I don’t think they’re ever going to be, even with efficient use of the Docker image cache.

If you’re willing to discard the idea of using your production containers for local development, or you run an interpreted stack that has no build process, you can change the rules of the game. You can mount your repository directory into the container, listen for file changes, and use a live reload tool (e.g. Fresh) to re-compile and re-launch your application within your container.

With some tomfoolery, this works reasonably well. It took us time to find and set up docker-osx-dev to mount and sync source folders efficiently, and several hours of putzing around with boot2docker to get inotify working properly, but we did arrive at a working solution.

But when we stepped back and looked at the beast we’d birthed, we could find no compelling advantages to it. We had been using foreman to start all our services locally, and foreman start is incredibly fast compared to docker-compose up. We inherited all the added complexity of managing boot2docker in addition to the Docker containers themselves. Our setup documentation tripled in length.


Our original motivation for trying Docker for local development was an errant brew update that broke some of our critical services locally (memcached and elasticsearch). In the end, we decided that running these backing services via docker-compose made plenty of sense, and do end up simplifying setting up and running a local development environment. On the other hand, we moved back to running our own microservices locally via foreman. We haven’t looked back since.

03 Aug 2015

Launched: Environments

LaunchDarkly now supports multiple environments!

Environments let you manage your feature flags throughout your entire continuous delivery pipeline, from local development to QA, staging and production. When you create your LaunchDarkly account, we’ll provide you with two environments, called Test and Production. Out of the box, you can use Test to set up feature flags for your non-production environments, while keeping your rules and data separate from your Production environment.

It’s incredibly easy to switch environments— just select your environment from the dropdown on the sidebar. When you create a flag, you’ll get a copy of that flag in every environment. Each flag can have different targeting and rollout rules for each environment. So you can roll a flag out to 100% of your traffic in staging, while keeping it ‘off’ in production.


Each environment has its own API key— use your Test key in your SDK for local development, staging, and QA, and reserve your Production API key for your production environment.

Environments are also completely customizable— you can create new environments, rename them, or delete them. You can even change the sidebar swatch color for your environment— make your Production environment red, for example, to give yourself a visual reminder that you’re modifying the rules for your live customer base.


Check out our documentation to learn more!