A new way to build feature flags
Feature flags are great. They’re a simple way to turn features on or off, they allow you to incrementally publish parts of a feature without worry, and let you A/B or internally test new ideas with low risk.
But it’s easy for teams to end up with dozens (or hundreds) of them and completely lose track: what exactly did show-banner-v2 do again?
Wrapping your code in logic every few steps is already messy without the added mental burden that booleans can interact in odd ways, and you can’t easily tell what your flow really looks like with a given combination of flags turned on.
The JSON patch feature can give us a better approach.
Why boolean flags are not it
Consider a familiar pattern
{
"darkModeEnabled": true,
"experimentalLayoutEnabled": false
}
Your code will look like
if (darkModeEnabled) {
theme = "dark";
contrast = "high";
}
if (experimentalLayoutEnabled) {
layout = "grid";
showSidebar = false;
}
Every new flag adds another cognitive branch. This is classic technical debt.
Enter, and scene: JSON patches
Your base config may start at
{
"theme": "light",
"contrast": "normal",
"layout": "standard",
"showSidebar": true
}
Each new feature can now be defined as a JSON patch, which is just a small list of declarative changes. You don’t have to juggle multiple flags for different parts of a feature - it all lives here
Dark Mode:
[
{ "op": "replace", "path": "/theme", "value": "dark" },
{ "op": "replace", "path": "/contrast", "value": "high" }
]
Experimental Layout:
[
{ "op": "replace", "path": "/layout", "value": "grid" },
{ "op": "replace", "path": "/showSidebar", "value": false }
]
Simply apply patches
let config = baseConfig;
config = applyPatch(config, darkModePatch);
config = applyPatch(config, experimentalLayoutPatch);
And get a beautiful little prebuilt config for each user
{
"theme": "dark",
"contrast": "high",
"layout": "grid",
"showSidebar": false
}
Why it’s the better way
- Each feature is self describing, and the patch itself is the documentation.
- Each patch is composable on it’s own, and you can merge, diff or revert them just as easily as flags.
- Best of all, no complex branching needed. Your code can stay short and simple.