Five Minutes to Feature Flags
March 2, 2023
We’re going to add feature flagging to a node service in under five minutes using OpenFeature, the open, vendor-agnostic feature flagging SDK.
We’ll be working with a simple express server, but if you have any basic familiarity with JavaScript and node you should be able to follow along.
Hello, world
Here’s the service we’ll be working on:
Pretty much the most basic express server you can imagine - a single endpoint at /
that returns a plaintext “Hello, world!” response.
Once the service is running (node server.js
should suffice), we can test that it works:
Yep, looks good!
with cows, please
Let’s imagine that we’re adding a new, experimental feature to this hello world service. We’re going to upgrade the format of the server’s response, using cowsay!
However, we’re not 100% sure that this cowsay formatting is going to work out, so for now we’ll protect it behind a conditional:
routes.get('/', async (req, res) => {
// set this to true to test our new
// cow-based greeting system
const withCow = false
if(withCow){
res.send(cowsay.say({text:'Hello, world!'}))
}else{
res.send("Hello, world!")
}
})
By default, our service continues to work exactly as it did before, but if we change withCow
to true
then our response comes in an exciting new format:
the crudest flag
That withCow
boolean and its accompanying conditional check are a very basic feature flag - they let us hide an experimental or unfinished feature, but
also easily switch the feature on while we’re building and testing it.
introducing OpenFeature
Managing these flags by changing hardcoded constants gets old fast though. A team that uses feature flags in any significant way soon reaches for a feature flagging framework. Let’s move in that direction by setting up the OpenFeature SDK:
$> npm install @openfeature/js-sdk
import { OpenFeature } from '@openfeature/js-sdk'
const featureFlags = OpenFeature.getClient()
routes.get('/', async (req, res) => {
const withCows = await featureFlags.getBooleanValue('with-cows', false)
if(withCows){
res.send(cowsay.say({text:'Hello, world!'}))
}else{
res.send("Hello, world!")
}
})
We’ve installed and imported the @openfeature/js-sdk
npm module, and used it to create an OpenFeature client called featureFlags
. We then call getBooleanValue
on that client to find out if the with-cows
feature flag is true or false. Depending on what we get back we either show the new cow-based output, or the traditional plaintext format.
Note that when we call getBooleanValue
we also provide a default value of false. Since we haven’t configured the OpenFeature SDK with a feature flag provider yet, it will always return that default value:
configuring OpenFeature
Without a feature flagging provider OpenFeature is pretty pointless - it’ll just return default values. Instead we want to connect our OpenFeature SDK to a full-fledged feature flagging system - a commercial product such as LaunchDarkly or Split, an open-source system like FlagD, or perhaps a custom internal system - so that it can provide flagging decisions from that system.
Connecting OpenFeature to one of these backends is very straightforward, but it does require that we have an actual flagging framework set up. For now, just to get started, let’s just configure a really, really simple provider that doesn’t need a backend:
import { MinimalistProvider } from '@moredip/openfeature-minimalist-provider'
const FLAG_CONFIGURATION = {
'with-cows':true
}
const featureFlagProvider = new MinimalistProvider(FLAG_CONFIGURATION)
OpenFeature.setProvider(featureFlagProvider)
const featureFlags = OpenFeature.getClient()
This minimalist provider is exactly that - you give it a hard-coded set of feature flag values, and it provides those values via the OpenFeature SDK.
In our FLAG_CONFIGURATION
above we’ve harded-coded that with-cows
feature flag to true, which means that conditional predicate in our express app will now evaluate to true, which means that our service will now start providing bovine output:
If we changed that with-cows
value to false, we’d see the more boring response:
moving to a full feature-flagging system
We’ve gotten started with OpenFeature using a very simple but extremely limited provider. The beauty of OpenFeature is that we can transition to a real feature-flagging system when we’re ready, without any change to how we evaluate flags. It’s as simple as configuring a different provider. For example:
We can get started with feature flags with low investment and low risk, and once we’re ready, it’s just a few lines of code to transition to a full-featured, scalable backend.
next steps
To learn more about OpenFeature, check out their documentation here. Specifically, you can read more about how the evaluation API works, what tech stacks are supported, or read more tutorials about using OpenFeature in a variety of tech stacks.
We strive to provide a welcoming, open community. If you have any questions - or just want to nerd out about feature flags - the #OpenFeature channel in the CNCF slack is the place for you.