notes.dt.in.th

Simple front-end feature flags

To embrace trunk based development and gain its benefits we must be able to merge pull requests quickly (or pushing straight to the main branch). However, in a project that doesn’t have a facility to allow this, it can be challenging.

Let’s say you are rewriting a complex piece of JavaScript code.

Now you’re not sure if your re-written version is correct. You fear that your new version will break on production^[Especially if you work on projects that deploys the main branch to production automatically thanks to tools like Vercel and Netlify], so you don’t have the confidence to merge your code until it is very thoroughly tested. Your branch ends up being long-lived rather than short-lived.

One way to solve this issue is to allow two versions of code to exist and create feature flags. You can go fancy and use tools like Unleash or LaunchDarkly, or you can use a simple client-side feature flag implementation shown here.

Client-side feature flag implementation

let flagSet: Set<string> | undefined

export function isQueryFlagEnabled(flagName: string) {
  if (!flagSet) {
    flagSet = new Set(
      (new URLSearchParams(window.location.search).get('flags') || '')
        .split(',')
        .filter(Boolean)
    )
  }
  return flagSet.has(flagName)
}
JavaScript version
let flagSet

export function isQueryFlagEnabled(flagName) {
  if (!flagSet) {
    flagSet = new Set(
      (new URLSearchParams(window.location.search).get('flags') || '')
        .split(',')
        .filter(Boolean)
    )
  }
  return flagSet.has(flagName)
}

Allowing two versions of code to exist at the same time

Instead of rewriting your component in place, replacing the old version, you can keep both versions in your codebase and use the isQueryFlagEnabled function to switch between them like this:

// Layout.js
import { isQueryFlagEnabled } from './QueryFlags'
import LayoutOld from './LayoutOld'
import LayoutNew from './LayoutNew'

export default isQueryFlagEnabled('new-layout') ? LayoutNew : LayoutOld

Activating the flag

To activate the flag, add the ?flags=new-layout query parameter to the URL.

Most users will see the old layout, while you can activate the flag during development to work on the new layout. Now you can safely merge your unfinished code into the main branch without the fear of breaking production.