Did you know that it is possible to add feature flags to your application simply by adding a JSON file containing the flags? Read on and I'll show you how to do it in NodeJS.
Zero restarts or downtime, just a fully dynamic application, all by using a JSON file.
Start without Feature Flags
Start the tutorial at the beginning, with a simple node app that has no feature flagging capabilities.
The app is a simple HTTP server which renders a static HTML page but, while rendering, replaces the placeholder text BACKGROUND-COLOUR
with the hex value returned from getBackgroundColour()
.
Create a package.json
file like this:
{
"name": "MyApp",
"version": "0.1.0",
"private": true,
"dependencies": {
},
"scripts": {
"start": "node app.js"
}
}
Next, create app.js
like this:
var fs = require('fs');
var http = require('http');
var port = 9123;
var html = fs.readFileSync('index.html').toString();
var getBackgroundColour = async function() {
return "#AAEEDD";
}
// ===========================================================
// This is our main HttpServer Handler
// ===========================================================
var server = http.createServer(async function (req, res) {
res.writeHead(200, 'OK', {'Content-Type': 'text/html'});
// replace background colour placeholder with real hex value
var finalHtml = html.replace(/BACKGROUND-COLOUR/g, await getBackgroundColour());
res.write(finalHtml);
res.end();
});
// Listen on port 9123, IP defaults to 127.0.0.1
server.listen(port);
// Put a friendly message on the terminal
console.log('Server running at http://127.0.0.1:' + port + '/');
console.log("Info", "Service is up and running - feed me with data!");
Finally, create a file called index.html
with this content:
<html>
<head>
<title>Demo</title>
<style>
body {background-color: BACKGROUND-COLOUR };
</style>
</head>
<body>
<div style="text-align:center">
<h1>A Demo Page...</h1>
<p>This is a simple demo page. The background colour is: BACKGROUND-COLOUR</p>
</div>
</div>
</body>
</html>
Run Simple App
Run the app with npm run start
and you should see this:
> MyApp@0.1.0 start
> node app.js
Server running at http://127.0.0.1:9123/
Info Service is up and running - feed me with data!
Try changing the hex value from "#AAEEDD"
to any other valid hex value. It will work, but you will need to restart the application to refresh the colour.
In today's world, restarts and / or redeployments often equal downtime. Downtime is the enemy!
Let's fix the app so we can change colour without any restarts or downtime.
Add Feature Flags
It is time to add feature flags to your application. Create a file called flags.json
and add this content:
{
"$schema": "https://flagd.dev/schema/v0/flags.json",
"flags": {
"background-colour": {
"state": "ENABLED",
"variants": {
"white": "#D6D4D2",
"green": "#73A53E",
"orange": "#FF7C00",
"lime": "#D3D309",
"blue": "#4AB9D9"
},
"defaultVariant": "green"
}
}
}
Replace app.js
with this content (notice the new OpenFeature code and modified getBackgroundColour
implementation):
var fs = require('fs');
var http = require('http');
var port = 9123;
var html = fs.readFileSync('index.html').toString();
var {OpenFeature} = require("@openfeature/server-sdk")
var {FlagdProvider} = require("@openfeature/flagd-provider")
var getBackgroundColor = async function() {
const backgroundColour = await client.getStringValue("background-colour", "#FFFFFF", { });
return backgroundColour;
}
// OpenFeature Initialisation Code
// Register your feature flag provider
OpenFeature.setProvider(new FlagdProvider());
// create a new client
const client = OpenFeature.getClient();
// =======================================================
// This is our main HttpServer Handler
// =======================================================
var server = http.createServer(async function (req, res) {
res.writeHead(200, 'OK', {'Content-Type': 'text/html'});
// replace background colour placeholder with real hex value
var finalHtml = html.replace(/BACKGROUND-COLOUR/g, await getBackgroundColor());
res.write(finalHtml);
res.end();
});
// Listen on port 9123, IP defaults to 127.0.0.1
server.listen(port);
// Put a friendly message on the terminal
console.log('Server running at http://127.0.0.1:' + port + '/');
console.log("Info", "Service is up and running - feed me with data!");
Instead of returning a static value, the code above uses OpenFeature and the Flagd provider (feature flag backend) to retrieve flag values (we will see how flagd reads the JSON file soon). If the feature flag system is offline or unavailable for whatever reason, a safe fallback value of #FFFFFF
is returned.
Now modify package.json
to look like the code below:
{
"name": "MyApp",
"version": "0.2.0",
"private": true,
"dependencies": {
"@openfeature/flagd-provider": "^0.12.0",
"@openfeature/server-sdk": "^1.13.2"
},
"scripts": {
"start": "node app.js",
"dev_linux": "export FLAGD_RESOLVER=in-process && export FLAGD_OFFLINE_FLAG_SOURCE_PATH=flags.json && node app.js",
"dev_windows": "set FLAGD_RESOLVER=in-process&&FLAGD_OFFLINE_FLAG_SOURCE_PATH=flags.json&&node app.js"
}
}
The only difference is that we've added dependencies
for OpenFeature
and flagd
. We also have 2 additional scripts, which set some important environment variables: FLAGD_RESOLVER
and FLAGD_OFFLINE_FLAG_SOURCE_PATH
. This is how flagd knows to read from a local file. The in-process
resolver is the "magic" that means you have a feature flag system "inside" your code logic.
Run Feature Flag Enabled App
Save the files and install the dependencies by running npm install
once.
Fire up the app by running the appropriate command (depending on your OS): npm run dev_linux
(for linux and macos) or npm run dev_windows
(for windows).
You should see:
% npm run dev_linux
> MyApp@0.2.0 dev_linux
> export FLAGD_RESOLVER=in-process && export FLAGD_OFFLINE_FLAG_SOURCE_PATH=flags.json && node app.js
Server running at http://127.0.0.1:9123/
Info Service is up and running - feed me with data!
The application is green because the defaultVariant
in flags.json
is green
which maps to the hex value "#73A53E"
.
Change App Colour at Runtime
Change the defaultVariant
in flags.json
to a different variant
key such as orange
. Save flags.json
and refresh the browser window (do not restart the node app).
You should see this:
Add Another Colour Choice at Runtime
Leave the node app running and add a new Key: Value
pair to the variants
block in flags.json
. Set the defaultVariant
to your new Key
and refresh the browser page.
For example, I'm adding a new red
variant:
{
"$schema": "https://flagd.dev/schema/v0/flags.json",
"flags": {
"background-colour": {
"state": "ENABLED",
"variants": {
"white": "#D6D4D2",
"green": "#73A53E",
"orange": "#FF7C00",
"lime": "#D3D309",
"blue": "#4AB9D9",
"red": "#FF0000"
},
"defaultVariant": "red"
}
}
}
Migrate to another Feature Flag Vendor
One of the powers of OpenFeature is that it allows you to easily migrate to different vendors.
For example, migrating to DevCycle (or any other provider) is almost just a case of replacing references to flagd
with devcycle
:
OpenFeature.setProvider(new FlagdProvider());
to
OpenFeature.setProvider(devcycleClient.getOpenFeatureProvider());
All compatible feature flag vendors and integration instructions can be found on the OpenFeature ecosystem page.
See part two to add runtime contextual awareness to your feature flagging.
Top comments (0)