When a Simple True/False Isn't Enough: Placing Feature Flags in Your Code
You've built a new feature. The code compiles, tests pass, and you're ready to ship. But you don't want to flip the switch for everyone at once. Maybe you want internal testers first. Maybe only users in Asia. Maybe just 10 percent of traffic.
This is where feature flags come in. They let you separate deployment from release: you can put new code into production without making it visible to everyone. But how exactly do you place these flags in your code without turning it into a mess of tangled conditions?
The Simplest Flag: A Boolean Switch
At its core, a feature flag is just a conditional branch. If the flag is on, run the new code. If it's off, run the old code. The most basic form looks like this:
if fiturXEnabled:
show_new_feature()
else:
show_old_feature()
Here, fiturXEnabled is a boolean variable. Set it to True, and users see the new feature. Set it to False, and they see the old one. Simple.
But there's a catch: the flag's value must be determined before the code runs. If you want to change it without redeploying, you need to read the value from somewhere outside the code itself. That could be a configuration file, an environment variable, or a remote service. We'll cover remote control of flags later, but for now, let's focus on when a simple boolean flag is enough.
A boolean flag works well when your feature is small and you only need two states: on or off. For example, imagine a "print report" button that was previously restricted to admins. Now you want to open it to all users. You add a flag called printReportForAllUsers. When True, the button appears for everyone. When False, only admins see it. Done.
When Simple Isn't Enough: Conditional Flags
Sometimes you need more nuance. Maybe the new feature should only be visible to users with specific IDs. Maybe only users in a particular region. Maybe only 10 percent of traffic, randomly selected. A simple boolean can't handle this.
You need a conditional flag. The flag itself is still a boolean, but the logic that determines its value depends on context. The simplest approach is to add conditions outside the flag:
if fiturXEnabled and user.id in trial_user_list:
show_new_feature()
else:
show_old_feature()
This works, but trial_user_list must be managed separately. If the list changes frequently, you need a way to update it without redeploying. That adds complexity.
A cleaner approach is to use a flag provider. A flag provider is a function or library that accepts context (like user ID, region, device type) and returns a flag value based on predefined rules. Your code becomes:
if flag_provider.is_enabled("featureX", user=current_user):
show_new_feature()
else:
show_old_feature()
Behind the scenes, the flag provider checks the rules: Is this user in the trial group? Does their region match? Has the traffic percentage been met? You don't need to rewrite that logic every time you use the flag.
Keeping Your Code Clean
The more flags you add, the more conditional branches appear in your code. Without discipline, you end up with nested if statements that are hard to read and harder to maintain.
A few principles help:
One flag, one responsibility. Don't cram multiple conditions into a single flag. If you need to control visibility by region and by user role, use two separate flags. It's clearer and easier to remove later.
Place flags at the right level. Put the flag as close to the feature's entry point as possible. For a UI component, that might be the component's render function. For an API endpoint, it might be the handler. Avoid scattering the same flag across multiple layers of your code.
Plan for flag removal. Every flag you add is temporary code. When the feature is fully rolled out, you'll remove the old code path and the flag. Write your flags so they're easy to find and delete. Group related flags together. Use consistent naming like featureX_enabled or featureX_percentage.
A Practical Checklist
Before you write your next feature flag, run through these points:
- Can this feature be controlled with a simple boolean, or do you need conditional logic?
- Where will the flag value come from? Hardcoded, config file, environment variable, or remote service?
- Is the flag placed at the right level, close to where the feature is used?
- Does the flag have a single, clear responsibility?
- Have you planned how to remove the flag and the old code path later?
What Comes Next
Once your flag is in the code, the next question is how to change its value without redeploying. You need a way to control flags remotely, whether through a configuration file that gets reloaded, environment variables that are updated, or a dedicated dashboard. That's where the real power of feature flags shows up: you can turn features on and off, roll out gradually, and react to problems without touching the deployment pipeline.
But none of that matters if your flags are messy. Start with clean, well-placed flags in your code. The rest follows.