Feature Flags in JavaScript with Vanna
Tags: devops, webdev, javascript
Published: 2018-09-06 13:14:43

---
title: Feature Flags in JavaScript with Vanna
published: true
description: Vanna is an easy-to-use feature flagging library. It's lightweight and currently used in production at PBS. In this tutorial we'll go through the easiest way to get started.
tags: devops,webdev,javascript
---


## I See a Red Button

Vanna is an open source feature flagging library written and used at [PBS]. Let's dive into the [JavaScript client]. To set up our tutorial, a story.

Mick is a front-end developer. The design team asked Mick to change the color of a red button to black. Product Management isn't ready to go all-in on the black button. Design and Product Management ask our prodigal engineer if there's a way to hedge our bets. They want to show the experimental black button to a small group of users. Mick smiles and puts on his shades. 😎

Here's a brief example of how Vanna lets you do this:

```javascript
// 👇 An instance of vanna client - implementation to come
import features from "app/features"; 

const paintItBlack = features.variation("paint-it-black")

if (paintItBlack) {
  // Render experimental black button
} else {
  // Render red button
}
```

This is feature flagging at its simplest. With feature flagging you can [merge to the trunk] more frequently. You can reduce risk by limiting new, volatile code to a subset of users. Vanna let's you do this in a way that's controlled outside of your application code. This unlocks another trait of continuous delivery.

A desirable goal of continuous delivery is to decouple deployments from releases. Deployments are the act of moving code to a server. Releases are the act of making code paths available to users. You can read more in [this Hacker Noon article].  To decouple releases from deployments Vanna receives its features from a JSON response. This allows us to update feature availability without doing a code deployment.

## Creating Features

Let's dive into the shape of the feature response. The response looks like this:

```javascript
{
  "features": {
    "paint-it-black": {
      "slug": "i-want-to-paint-it-black",
      "enabled": true,
      "targetSegment": ["alpha-tester"]
    }
  }
}
```

The feature response contains any number of feature objects. In our sample
there is one feature, `"paint-it-black"`. The feature has three
properties:

- `"slug"` - This names the feature. It's useful for feature
  identification when you're only given the feature values. We'll use it for
  overriding feature availability in our advanced example.
- `"enabled"` - This key makes the feature available. Think of it as
  the master circuit breaker. If this is `false`, the feature will
  be off for everyone.
- `"targetSegment"` - Features target users. You make a feature
  available to groups of users with this key. We'll see how users identify as a
  `userSegment` when we instantiate a `new VannaClient`.

There is no console interface to create this JSON response at the moment. Right now we'll write the JSON by hand and make it accessible through a CDN. An admin interface and API service to create this response is a future enhancement. Hand-crafting the JSON was the smallest step we could take towards developing the Vanna library. Taking this MVP approach makes it easier for us to experiment and iterate.


## Using vanna-js

In our simple example we assumed the availability of the client library. Let's implement it.

We'll set `userSegment` based on the presence of a cookie. See our [previous post] on setting cookies for feature flags.

```javascript
// app/features.js
import { VannaClient } from "@pbs/vanna";
import Cookies from "js-cookie";

const isAlphaTester = Cookies.get("alpha-tester");

const client = new VannaClient({                                              
  uri: "https://cdn.com/features.json",                    
  userSegment:  isAlphaTester ? "alpha-tester" : "regular",           
  fallbacks: {                                                                
    "paint-it-black": false                                              
  }                                                                          
});                                                                           
```

When you instantiate a `new VannaClient` you're responsible for:

- `uri` - This is the location of the JSON feature control response.
- `userSegment` - This is the user's group. Vanna enables the feature for this
  user on a match to an enabled `"targetSegment"`.
- `fallbacks` - This sets the default behavior for feature flags. Note that a
  fallback must be set for every feature in the JSON response.

We can now use Vanna to finish our task. In our initial example we created a boolean to split our code path with:

```javascript
const paintItBlack = features.variation("paint-it-black")
```

Vanna's `variation()` method takes the feature's `"targetSegment"` and client's `userSegment` into consideration. On a match between the two the method returns `true`.

With this tutorial you can use Vanna as a feature flagging library. You can decouple deployments from releases. You can ship software more quickly with a lower risk. Using Vanna in this way for feature flagging is perfect for simple use cases. Advanced options are available for power users who need more customization.

## Overriding Variations

Controlling features with a single `userSegment` seems coarse. What if we want finer control? What if I want to enable a specific feature regardless of my `userSegment`? The Vanna client allows you to override variation eligibility. We can extend our previous [post] about toggling flags on feature-specific cookies. We'll allow Vanna to opt-in to a feature based on the presence of named cookies. The following highlighted blocks show how we can add to our previous Vanna client:


```javascript
// app/features.js
import _ from "lodash";
import { VannaClient, getFeatureVariation } from "@pbs/vanna";
import Cookies from "js-cookie";

function getVariationOverride(featureSlug) {
  const featureKey = `feature:${featureSlug}`;
  const overrideValue = Cookies.get(featureKey);
  if (overrideValue) {
    return overrideValue === "true";
  }
  return undefined;
}

const isAlphaTester = Cookies.get("alpha-tester");

const client = new VannaClient({                                              
  uri: "https://cdn.com/features.json",                    
  userSegment:  isAlphaTester ? "alpha-tester" : "regular",           
  fallbacks: {                                                                
    "paint-it-black": false                                              
  },
  _overrides: {
    getFeatureVariation: (feature, { userSegment }) => {
      const variation = getFeatureVariation(feature, { userSegment });
      const overrideVariation = getVariationOverride(feature.slug);
      return _.isUndefined(overrideVariation) ? variation : overrideVariation;
    }
  }
});                                                                           
```

With this additional code a user can opt-in to features that are not part of their `userSegment`. In our example if a user doesn't have the `"alpha-tester"` cookie, but does have a `"feature:i-want-to-paint-it-black"` cookie, they will see the black button. The opposite use case also works. An `"alpha-tester"` can opt out of a feature by setting a named cookie to `"false"`. This variation override allows for finer control over feature availability. We've used cookies to override the variation, but you could use local storage or anything that's available in JavaScript.

The [vanna-js-client] is an open source project. Please check out the brief, readable source code. It's a lightweight way to add feature flags to your JS project.

[PBS]: https://www.pbs.org
[JavaScript client]: https://github.com/pbs/vanna-js-client
[merge to the trunk]: https://accelerate.delivery/trunk-development-feature-flags/
[this Hacker Noon article]: https://hackernoon.com/decouple-deployment-from-release-b4b9182b6a46
[previous post]: https://accelerate.delivery/setting-cookie-flags-django/
[post]: https://accelerate.delivery/toggle-django-views-with-cookie-flags/
[vanna-js-client]: https://github.com/pbs/vanna-js-client