Unlock the Power of Feature Flags in React

Are you ready to take control of your app’s development and unleash its full potential? In this tutorial, we’ll show you step-by-step how to set up feature flags in React and start reaping the benefits of this powerful tool. Whether you’re new to feature flags or looking to optimize your workflow, this guide has everything you need to get started. So join us as we take a deep dive into the world of feature flags and discover how they can help you build, test and deploy with confidence.

Introduction

Unleash the full potential of your app and take control of its development with feature flags. These powerful tools allow you to build, test and deploy new features seamlessly and safely, without disrupting the smooth functioning of your production app. Whether you’re A/B testing new interfaces, rolling out new features or tailoring the user experience based on roles and permissions, feature flags give you the flexibility to innovate and evolve at your own pace. Empower yourself with the ability to experiment, iterate and optimize with feature flags.

Common use-cases for Feature Flags

A feature flag is like a secret switch that lets you turn certain things on or off in your computer program. It’s like a magic button that can make different parts of your program appear or disappear.

Here are some examples of what people use feature flags for:

  1. If someone is building a new game, they might use a feature flag to hide the new levels from people who haven’t finished the old levels yet.
  2. Imagine you’re making a new recipe, but you’re not sure if people will like it. You can use a feature flag to only show the new recipe to some people and see how they like it before you show it to everyone.
  3. In a classroom, if the teacher wants to give a test to a small group of students first to see how well they do before giving it to the whole class.
  4. In all these examples, the feature flags allow to test, experiment and roll out new things gradually, making sure that it works well before giving it to everyone.

Types of Feature Flags

There are are a range of experiments and different feature flags you can use depending on your use-case.

  1. A/B Testing: This type of feature flag allows you to show different versions of a feature to different groups of users. For example, you could show a new design to half of your users and the old design to the other half, and then compare how they use the feature to see which one is better.
  2. Multi-Variant Testing: Similar to A/B testing, but with more than two variations. This allows you to test multiple variations of a feature with different groups of users to see which one is the best.
  3. Gradual Rollout: This type of feature flag allows you to slowly roll out a new feature to a small group of users first and then gradually increase the number of users over time. This way you can make sure that the feature is working correctly before making it available to everyone.
  4. Dark Launching: This type of feature flag allows you to test a new feature in production with a small group of users without them knowing. This way you can make sure that the feature is working correctly before making it available to everyone.
  5. Kill Switch: This type of feature flag allows you to quickly turn off a feature that is causing problems. It’s like an emergency button that you can press to make the feature disappear if something goes wrong.
  6. User Targeting: This type of feature flag allows you to show a feature to a specific group of users based on certain criteria, such as their location, device type, or account level.

Best Practices

Before we begin writing some code, let’s just touch on some best practices for running experiments and feature flags.

  1. Keep feature flags small and focused: Instead of using one feature flag for multiple features, use a separate flag for each feature. This will make it easier to manage and test each feature individually.
  2. Use a centralized management system: Use a system to manage all your feature flags in one place. This will make it easier to track which flags are active, who created them, and when they will be removed.
  3. Have a clear plan for removing flags: Have a plan in place for when to remove flags after they are no longer needed. This will help keep your codebase clean and maintainable.
  4. Use feature flags in development, staging and production: By using feature flags throughout the development process, you can catch issues early and make sure the feature is working correctly before releasing it to users.
  5. Monitor and measure the impact of flags: Keep track of how users are interacting with features behind flags, and use that data to inform decisions about whether to keep or remove a flag.
  6. Communicate and collaborate: Make sure that everyone on your team knows how to use feature flags, what they’re being used for, and how they can be removed. This will help prevent confusion and ensure that the flags are being used effectively.
  7. Secure your feature flags: Keep your flags secure by using authentication and authorization, so that only authorized users can access and change them.

Building your own Feature Flag Functionality

Ok, let’s start building a quick solution and discuss the architecture for this demo.

  1. React Application using NextJs
  2. Server Side Application using Express
  3. Postgres Database for storing Feature Flag Data

Setting up the Database

First let’s use Docker to setup our Postgres Database locally.

docker pull postgres
docker run -d \
--name some-postgres \
-e POSTGRES_PASSWORD=mysecretpassword \
-e PGDATA=/var/lib/postgresql/data/pgdata \
-v /custom/mount:/var/lib/postgresql/data \
postgres

Next let’s create two tables in our database for feature flags.

CREATE TABLE feature_flags (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
active BOOLEAN NOT NULL,
description TEXT NOT NULL,
start_date TIMESTAMP,
end_date TIMESTAMP,
percentage INT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE feature_flag_users (
id SERIAL PRIMARY KEY,
user_id VARCHAR(255) NOT NULL,
feature_flag_id INT NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);

Let’s go ahead and create our first feature flag.

INSERT INTO feature_flags(name, active, description)
VALUES ('test', true, 'testing feature flags);

Creating an API Service for Feature Flags

Next let’s go ahead and create an API Service for the feature flags. We’ll need to install some dependencies to begin:

We’ll install pg a package

npm install pg

Next we’ll setup a file called db.js as a library to access a postgres pool.

const Pool = require("pg").Pool;

const connectionString = `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`;
console.log(connectionString);
// Create a new pool with the environment variables

const p = new Pool({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});

module.exports = p;

Now we can go ahead and create an app as follows.

const express = require("express");

const pl = require("./db");

const app = express();
// ADD THIS
var cors = require("cors");
app.use(cors());
app.use(express.json());

const port = 3001;

app.get("/", (req, res) => {
res.send("Hello World!");
});

app.get("/api/feature-flags/:name", async (req, res) => {
const client = await pl.connect();
try {
const flag = await client.query(
`SELECT * FROM feature_flags WHERE name=$1`,
[req.params.name]
);
// return the flag rows
console.log(flag.rows[0]);
res.json(flag.rows[0]);
} finally {
client.release();
}
});

app.post("/api/feature-flags/:name/enable", async (req, res) => {
console.log("req.body", req.body.userId);
const client = await pl.connect();
try {
const user_id = req.body.userId;

// if user_id is not null
//console.log(req.body);
// if user_id is not null or undefined
if (user_id) {
console.log("querying");
const flag = await client.query(
`SELECT * FROM feature_flags WHERE name=$1`,
[req.params.name]
);

if (flag.rows.length === 0) {
res.json({ message: "failure" });
return;
} else {
await client.query(
`INSERT INTO feature_flag_users (user_id, feature_flag_id, updated_at) VALUES ($1, $2, NOW())`,
[user_id, flag.rows[0].id]
);
res.json({ message: "success" });
}
//console.log(flag.rows[0].id);
} else {
res.json({ message: "failure" });
}
} finally {
client.release();
}
});

// start the Express server and restart it on file changes
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});

We can start this service via node app.js or alternative wrap it in the package.

Create your own Feature Flags with React

Now let’s go ahead and create some feature flags in our React Application. We’ll create our application using NextJS and install a framework called axios that will help us send http requests to the service we created in the previous step.

npx create-next-app@latest  front-end --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/learn-starter"
cd front-end
npm install axios

Next create a file utils/useFeatureFlag.ts for us to use in a our project.

import { useState, useEffect } from 'react';
import axios from 'axios';

// async function
export async function enableFeatureFlag(flagName, userId) {
const url = `http://localhost:3001/api/feature-flags/${flagName}/enable`;
console.log("url: ", url);

const res = await axios.request({
method: 'POST',
url: url,
headers: {
'Content-Type': 'application/json'
},
data: {
userId: userId
},

})
console.log("res: ", res);
}


export function useFeatureFlag(flagName: string) {
const [flagEnabled, setFlagEnabled] = useState(null);
const [enabledAt, setEnabledAt] = useState(null);
const [userId, setUserId] = useState(null);

useEffect(() => {
async function fetchData() {
const res = await axios.get(`http://localhost:3001/api/feature-flags/${flagName}`).then(
(res) => {
console.log("res: ", res);
console.log("res.data.current_percentage: ", res.data.status)
// if (Math.random() < (res.data.current_percentage / 100)) {
// setFlagEnabled(true);
// } else {
// setFlagEnabled(false);
// }
if (res.data.active == true){
setFlagEnabled(true)
setEnabledAt(res.data.start_time);
} else {
setFlagEnabled(false)
}

const userId = typeof window !== 'undefined' ? localStorage.getItem('userId') : null
if (!userId) {
const userId = generateUserId()
localStorage.setItem('userId', userId)
setUserId(userId)
} else {
setUserId(userId)
}
}
)
}
fetchData();
}, [flagName]);

function generateUserId() {
return Math.random().toString(36).substr(2, 9);
}

return { flagEnabled, enabledAt, userId }
}

There is quite a bit going on above so let’s start by explaining some of the main functions:

  • useFeatureFlag — checks the flag name and checks to see if the feature flag exists and is active or enabled. If it is enabled we can then use it to enable the feature for the user and utilize that upstream in a component.
  • enableFeatureFlag — this takes in a flag name and userid and makes a call to our service to log that the user has enabled the feature.

Using Feature Flags in our React App

Next let’s use these utility methods in our ReactApp.

Now we can make some changes inpages/index.js to utilize the feature flag as follows:

import { useFeatureFlag } from "../utils/useFeatureFlag";

export default function Home() {
const { flagEnabled, enabledAt, userId } = useFeatureFlag("test");

if (flagEnabled) {
return (
<div>
This feature is enabled for user {userId} at {enabledAt}
</div>
);
} else {
return <div>This feature is disabled</div>;
}
}

Now we can go ahead and start our application and see this feature is enabled.

npm run dev

Conclusion

This is a quick guide if you are interested in building feature flags in your react application. There are also some great libraries and companies that are also useful to consider like LaunchDarkly, FlagSmith and Split. These libraries and companies provide a powerful set of tools and features that can help you manage and optimize your feature flags. Some of the benefits you can gain by using these libraries and companies include:

  • Easy integration with your existing React application: These libraries and companies are specifically designed to work with React, so you can easily add feature flags to your codebase without having to do a lot of additional work.
  • Advanced targeting and segmentation: These libraries and companies provide advanced targeting and segmentation capabilities, so you can deliver the right feature to the right user at the right time.
  • Real-time analytics and reporting: With these tools, you can easily track how users are interacting with your features and make data-driven decisions about what to keep and what to remove.
  • Scalability and reliability: These libraries and companies are built to handle large scale applications and provide reliability, so you can be sure your feature flags will work smoothly and without interruption.
  • Security: Many of these libraries and companies have built-in security features to ensure that your feature flags are protected from unauthorized access or tampering.

Overall, if you’re interested in building feature flags in your React application, these libraries and companies are definitely worth considering. They can provide you with powerful tools and features that can help you manage and optimize your feature flags, ultimately making your development process more efficient, and your application more stable and reliable.

If you made it this far, congratulations and thank you. Hope you enjoyed this article on feature flags and experiments.

Happy Coding!

--

--

Group Product Manager @Twilio - Part-Time Crossfit Athlete.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store