TutorialsAug 14, 202512 min read

Zero-downtime deployment with Flagsmith and CircleCI

Daniel Efe

Front-end Developer

As developers, we continually strive to improve our software. This often means rolling out new software features at a rapid pace. However, deploying new features to production is not without risk. From no real production testing to limited rollback options, traditional deployment can quickly become frustrating. The worst issues, though, usually stem from one thing: buggy features making their way into the hands of users.

Releasing a feature the traditional way means it goes live for every user, regardless of whether the feature is ready or not. When things go wrong, rolling back can be slow, difficult, or even impossible without causing downtime. To address this, Flagsmith, a feature flag tool, allows developers to enable or disable features at runtime without deploying new code.

In this tutorial, you will learn what feature flags are as well as their benefits. You will also integrate Flagsmith, a popular feature flag tool into a simple project. You will automate the whole process with CircleCI, a Continuous Integration and Deployment tool.

Prerequisite

To continue with this tutorial, you need:

  1. A GitHub account.
  2. A Flagsmith account.
  3. A CircleCI account.
  4. A Vercel account.
  5. Node.js version 14 or higher.

What are feature flags?

Imagine you are working on a dark mode feature for your app, and while it is not fully tested and ready for users to see yet, you still want to merge it into the main branch of your code so your team can continue building and testing collaboratively. Traditionally, the only way to do this will be to either comment the code out or avoid merging it altogether. But with feature flags you can commit the code and control when the feature gets turned on or off, without needing to redeploy.

So what exactly are feature flags? In simple terms, feature flags (or feature toggles) are a development technique that allows you to enable or disable a feature at runtime without having to redeploy your application. They act as conditional checks in your code that determine which portion of the codebase should be executed.

Feature flags give developers full control over when and how features are released. They allow developers to decide when features become visible to users, which subset of users can access them, and in which environment (production or staged) the feature is enabled.

Using feature flags in your code comes with certain benefits, including:

  • Reduced risk on feature release
  • Faster and more flexible releases
  • User targeting
  • Better testing in real-world scenarios

Reduced risk on feature release

Every user expects to get regular updates that improve the functionality of purchased software or apps. Developers need to meet these expectations by consistently rolling out new features. But sometimes, even the best features can cause unintended problems like slowing down applications and breaking existing functionality. Or maybe they just don’t fit well with the rest of the product.

Instead of fully launching a feature, you can release it behind a flag, so in case things go sideways, you won’t be scrambling to fix it or risk unhappy users. Instead, you could just turn the feature off, make improvements, and roll it out again when it is ready.

Faster and more flexible releases

Traditionally, once code is deployed, it becomes immediately available to users whether it is bug-free or not. But with feature flags, everything changes. Developers can now deploy code to production without instantly releasing it to users.

This separation between deployment and release guarantees flexibility, as features can remain hidden behind a flag until the team decides they are ready to go live. Because teams are not forced to perfect a feature before deployment, smaller code changes can be shipped faster, with the full feature released only when it is stable or fully tested. This way, high-demand changes can be rolled out quickly even before the full feature is completed.

User targeting

With feature flags, developers can now target specific users to access certain application features while restricting access for others. For example, imagine you’re launching a new dashboard redesign in your app. Instead of releasing it to all users at once, you could enable it only for internal team members or a select group of beta testers.

This makes it easy to gather feedback and catch issues early, without impacting your entire user base. Developers can build all the necessary features into the same codebase but activate them only for specific user groups like paid subscribers, beta testers, or internal team members.

Better testing in real-world scenarios

Developers run multiple tests on applications, from unit tests to integration tests and more before deployment. But no test script can fully replicate how a feature will behave once it goes live. This is because testing in a controlled environment doesn’t always reflect real usage.

With feature flags, developers can simply release new features to a set of users and monitor how those features perform in real usage conditions. Teams can get first-hand information about how a feature performs under real-life conditions without risking a full-scale rollout.

Project setup

To better understand how feature flags work in real-world scenarios, you will clone a sample project and set up Flagsmith.

To get started, open your terminal. Run:

git clone --single-branch -b starter-template https://github.com/CIRCLECI-GWP/feature-flag-app.git
cd feature-flag-app

Note: The project used in this tutorial is a simple web application built with React. It includes a sign-up and log-in page that users must complete before gaining access. It also contains a dark mode feature which is currently commented out. This dark mode will serve as the test feature for implementing Flagsmith.

Next, initialize Git and push your cloned project to your GitHub repository.

Installing and configuring Flagsmith

With your project now pushed to a GitHub repository, it is time to install and configure Flagsmith.

To get started, sign in to your Flagsmith account.

Next, click the Create Project button on your Flagsmith dashboard. Enter your project name to continue.

Create project - Flagsmith

Within your created project, go to the Feature tab and click on the Create Feature button.

Create feature - Flagsmith

Enter the name of your flag and continue by clicking Create Feature.

Enter feature name

Next, click the SDK Keys tab and copy your Client-side Environment Key. You will need it later in the tutorial.

SDK key

Now, go to your terminal and install the Javascript Client for Flagsmith in your project. Run:

npm i flagsmith --save

Note: It is best to wrap your main.jsx file with the FlagsmithProvider so that Flagsmith can access your entire application via React context. This makes it easy for any component in your app to access feature flags.

To wrap your app with Flagsmith, open the src/main.jsx file and replace the existing code with the following:

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import { BrowserRouter } from 'react-router-dom'
import { AuthProvider } from './AuthContext.jsx'
import flagsmith from 'flagsmith'
import {FlagsmithProvider} from 'flagsmith/react'

createRoot(document.getElementById('root')).render(
  <FlagsmithProvider 
    options={{
      environmentID: "<YOUR_ENVIRONMENT_KEY>",
    }} 
    flagsmith={flagsmith}
  >
    <StrictMode>
      <BrowserRouter>
      <AuthProvider>
      <App />
      </AuthProvider>
      </BrowserRouter>
    </StrictMode>
  </FlagsmithProvider>,
)

In this sample code:

  • import flagsmith from 'flagsmith' imports the Flagsmith javascript SDK that interacts with the Flagsmith API.
  • import {FlagsmithProvider} from 'flagsmith/react' introduces the React-specific provider component that makes Flagsmith accessible to your app via React context.
  • This code passes your unique environment ID to connect your app to the correct Flagsmith project and environment:
<FlagsmithProvider options={{environmentID:"<YOUR_ENVIRONMENT_KEY>",}}

Note: Replace <YOUR_ENVIRONMENT_KEY> with your actual client-side Environment Key, present in your SDK Keys tab on the Flagsmith dashboard.

Next, open src/Components/Navbar/Navbar.jsx. This file contains your dark mode toggle feature that was previously commented out. Update its content to use Flagsmith by entering:

import React, { useState, useEffect } from 'react';
import imageOne from "../../assets/imageOne.png"
import { useFlags } from 'flagsmith/react';

const Navbar = () => {
  const [isActive, setIsActive] = useState(false);

  const flags = useFlags(['dark-mode-feature']);
  const darkModeEnabled = flags['dark-mode-feature']?.enabled;

  const toggleSwitch = () => {
    setIsActive(prev => !prev);
  };

  useEffect(() => {
    if (isActive) {
      document.body.style.background = "linear-gradient(to right, #0f2027, #203a43, #2c5364)";
      document.body.style.color = "white";
    } else {
      document.body.style.background = "linear-gradient(to right, #b3e5fc, #81d4fa)";
      document.body.style.color = "black";
    }

    const navLinks = document.querySelectorAll('nav a');
  navLinks.forEach(link => {
    link.style.color = isActive ? 'white' : 'black';
  });
  }, [isActive]);

  return (
    <div>
      <nav>
        <div>
        <img src={imageOne} alt="" />
        </div>
        <div className='head'>
        <a href="#">Home</a>
        <a href="#">About</a>
        <a href="#">Contact</a>
        <a href="/Signup">Logout</a>
        {darkModeEnabled && (
          <div className='darkmode'>
            <div className='first'>
              < i className='bxr  bx-brightness-half'  ></i> 
            </div>
            <div className={`second ${isActive ? 'active' : ''}`} onClick={toggleSwitch}>
              < i className='bxr  bxs-circle'  ></i> 
            </div>
            </div>
        )}
        </div>
      </nav>
    </div>
  )
}

export default Navbar

In this configuration:

  • import { useFlags } from 'flagsmith/react'; import the useFlags hook that allows you access to the feature flags provided by the FlagsmithProvider.
  • const flags = useFlags(['dark-mode-feature']); retrieves the current value of your dark-mode-feature flag set in your Flagsmith dashboard, ensuring only the specified flag is tracked for better efficiency.
  • const darkModeEnabled = flags['dark-mode-feature']?.enabled; checks if the dark-mode-feature is enabled in your flagsmith dashboard, and in a case where it is not, it avoids throwing an error by using optional chaining ?.

Commit and push changes to GitHub.

Finally, run your app in the browser. In your terminal, enter:

npm run dev

Go to http://localhost:5173 in your browser. After selecting Get started, the sign-up page will be displayed.

Signup page

To access the main application, fill in the required field and click Sign up.

App without feature

At this point, although the dark mode feature exists in your code, it’s not visible on the page because it has not yet been activated via Flagsmith.

To activate it, go to the Flagsmith dashboard and click the Features tab. Find dark-mode-feature, and toggle it on to activate.

Toggle feature on

A pop-up will appear confirming that this feature will be turned on in the development environment. Click Confirm to proceed.

Confirm toggle

After reloading your application, the dark mode toggle will be active and visible.

App with feature

You can click on the toggle switch to turn dark mode.

Darkmode feature activated

You can now control when dark mode feature goes live on your site, or you can roll it back without making changes to your codebase. All you have to do is go to your Flagsmith dashboard and toggle the feature on or off as needed.

Deploying the application to Vercel

With Flagsmith fully installed and configured in your application, it is time to deploy your app to a web hosting platform. This step will make your application publicly accessible, ensure your feature-flagged code is included in the deployed build, and also give you a chance to verify that your Flagsmith setup works correctly in a production environment.

In this tutorial, you will be deploying to Vercel, a popular platform for hosting modern front-end applications.

To get started, log in to your vercel account.

Next, click on the Add New Project button on the Vercel dashboard.

Add new project

In the Import Git Repository section, search for your Github project and click Import to continue.

Import project

A page with your project deployment configuration will be opened for you. Select Deploy to deploy your project.

Deploy project

Voila! Your app is now live. You can review your deployed webpage by clicking the preview image (thumbnail) shown on your Vercel dashboard.

View deployed project

Integrate CircleCI for zero-downtime deployment

So far, you have installed and configured Flagsmith in your project and successfully deployed your app to Vercel. Now you can integrate a CI/CD tool to help you automate future deployments and enforce consistency in your project every time changes are made to your code base.

CircleCI is a great tool for this process. Integrating CircleCI will ensure your application gets automatically built and deployed with every update, thereby eliminating human error and manual steps.

To begin integrating CircleCI, go to your project directory and create a .circleci folder at the root. Inside this folder, create a config.yml file.

Update your config.yml file with this configuration:

version: 2.1

jobs:
  build-and-deploy:
    docker:
      - image: cimg/node:22.16.0
    steps:
      - checkout

      - run:
          name: Install dependencies
          command: npm install

      - run:
          name: Build React App
          command: npm run build

      - run:
          name: Install Vercel CLI
          command: npm install -g vercel

      - run:
          name: Deploy to Vercel
          command: |
            vercel --token=$VERCEL_TOKEN --prod --yes

workflows:
  version: 2
  deploy_on_main:
    jobs:
      - build-and-deploy:
          filters:
            branches:
              only: main 

This CircleCI configuration runs in a Docker container using the cimg/node:22.16.0 image to maintain a consistent Node.js environment.

It contains a build-and-deploy job which installs necessary dependencies using the npm install command, builds the application using npm run build, installs Vercel using npm install -g vercel, and finally deploys the application using vercel --token=$VERCEL_TOKEN --prod --yes.

Commit and push changes to GitHub.

Set up the project in CircleCI

To set up your project on CircleCI, start by logging in to your CircleCI account.

Next, set up your project by following the steps outlined in the official guide to setting up a project on CircleCI.

Before you can trigger the pipeline, you need to set your Vercel token as an environment variable in CircleCI.

Head over to your Vercel dashboard and select Account settings.

Vercel account settings

Select Tokens from the sidebar. In the Create Token section, provide the token name, set the scope and expiration, and click Create.

Create token

Copy your token and set it as an environment variable in CircleCI. Use the key VERCEL_TOKEN and your token as the value.

You can now trigger the pipeline manually. It should execute successfully.

Successful Pipeline Build

Controlled rollouts with Flagsmith (target internal users)

Controlled rollout is a feature of Flagsmith that gives you the ability to release features to only a specific group of users. This means that developers can test new features in production with internal users before releasing them to everyone else, reducing the risk of failed releases and boosting team confidence.

Note: In this section, you will configure Flagsmith to make your dark mode feature available to internal users with emails ending with “@daneycorps.com”. Toggle your dark-mode-feature feature off on Flagsmith before you continue.

To implement controlled rollout with Flagsmith, go to your project dashboard on Flagsmith. Select Segments, then Create Segment.

Create segment

Next, fill out the:

  • Name: daneycorpuser.
  • Trait: isDaneycorpsUser.
  • Operator: Exactly Matches(=).
  • Value: true.

Click the Create Segment button to continue.

Go to Environments and click dark-mode-feature, then click Segment Overrides.

Segment override

Click Create a Segment Override, select daneycorpuser, and toggle the feature on. Click the Update Segment Overrides button to continue.

Update segment override

Update the src/AuthContext.jsx file by replacing the existing code with this:

import { createContext, useContext, useState, useEffect } from "react";
import flagsmith from "flagsmith";
const AuthContext = createContext();

export function AuthProvider({children}){
    const [user, setUser] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        const storedUser = localStorage.getItem('user');
        if(storedUser){
            setUser(JSON.parse(storedUser));

            const userData = JSON.parse(storedUser);
            flagsmith.identify(userData.email, {
                email: userData.email,
                isDaneycorpsUser: userData.email.endsWith('@daneycorps.com')
            });
        }
        setLoading(false);
    }, []);

    const login = (userData) => {
        setUser(userData);
        localStorage.setItem('user', JSON.stringify(userData));

        flagsmith.identify(userData.email, {
            email: userData.email,
            isDaneycorpsUser: userData.email.endsWith('@daneycorps.com')
        });
    };

    const logout = () => {
        setUser(null);
        localStorage.removeItem('user');
    };

    return (
        <AuthContext.Provider value={{user, login, logout, loading}}>
            {children}
        </AuthContext.Provider>
    );
}

export const useAuth = () => useContext(AuthContext);

The code in this sample uses the Flagsmith identify method to make the dark mode feature available to specific users:

  • flagsmith.identify(user.email); reveal the current user to Flagsmith by passing their email.
  • isDaneycorpsUser:userData.email.endsWith('@daneycorps.com')}); checks if the logged-in users belong to an organization by evaluating if their email addresses end with “@daneycorps.com”.

Now if you create an account with an email ending with @daneycorps.com, the dark mode feature will be present. For other email extensions, the dark mode feature will be unavailable.

Conclusion

In this tutorial, you learned about feature flags and some of their many benefits. You also learned how to integrate Flagsmith, a popular feature flag tool, into a simple web app project. You deployed your app to Vercel to test Flagsmith in production, while automating deployment with CircleCI, a popular CI/CD tool.

You explored how to use Flagsmith for controlled rollout, allowing you to target specific users with new features before releasing them to everyone.

Now you can implement all that you have learned in both new and existing projects.

You can review the complete tutorial code on GitHub.