keepcalculator

06 Numbers and Powers

Feature flags beyond hiding unfinished work

Card No. 06·54441 · Updated · Standard formula, shown below

Feature flags are best known for hiding unfinished code in production, but they are far more useful as a general-purpose runtime control for almost any behavior in your application. This article explains practical ways to use feature flags beyond simple release toggles, including gradual rollouts, operational controls, and experimentation, and gives concrete examples you can apply today.

What feature flags actually are

A feature flag (also called a feature toggle, feature switch, or conditional) is a mechanism that lets you turn a piece of functionality on or off without deploying new code. At its simplest, it is an if statement in your code that checks a value stored in a configuration file, a database, or a dedicated feature-management service. The flag can be evaluated at runtime, so you can change the behavior of a live system instantly, without a build or restart.

Flags are usually classified by their purpose. Release toggles hide incomplete features from users. Experiment toggles assign users to different variants. Ops toggles control system behavior during incidents. Permission toggles grant access to specific groups. Each type has different lifecycle expectations, and understanding the types helps you choose the right tool for the job.

Gradual rollouts and canary releases

Instead of releasing a new feature to everyone at once, you can use a flag to roll it out slowly. Start with 1% of users, watch error rates and performance, then increase to 10%, 50%, and 100%. This is often called a canary release or a percentage rollout. It reduces the blast radius of a bad deployment because you can stop the rollout by setting the flag to 0%.

For example, you might introduce a new checkout flow. The flag checks a hash of the user ID to decide which flow to show. If the new flow causes a spike in abandoned carts, you turn it off immediately, and users fall back to the old flow. This is far faster than rolling back a deployment, which could take minutes or hours and might require database migrations to undo.

Kill switches and operational controls

Flags are excellent for emergency shutdowns. A kill switch is a flag that disables a specific external integration, a background job, or a resource-intensive process when something goes wrong. For instance, if your payment provider has an outage, you can flip a flag to show a maintenance message instead of failing at checkout. If a third-party API starts returning errors, you can disable that integration and serve cached data.

Kill switches are most useful when they are coarse and simple. They should be set up before you need them, and they should be easy to flip by an on-call engineer. A common mistake is making a kill switch too fine-grained, so that in an emergency you have to find the right flag among hundreds. Keep a small set of well-documented operational flags that cover the most critical paths.

Experimentation and A/B testing

Feature flags are the backbone of modern A/B testing. You can assign users to different variants of a feature and measure which one performs better. For example, you might test two different headlines, two different pricing layouts, or two different onboarding sequences. The flag evaluation can be based on a random assignment, a user ID hash, or a targeting rule.

Experimentation flags are different from release flags because they are designed to be long-lived and to collect data. You need to ensure that a user sees the same variant every time, so the assignment must be sticky. You also need to avoid interaction effects: if two experiments affect the same metric, you need to run them in isolation or use proper statistical methods. Many teams use a dedicated experimentation platform, but even a simple flag with a random assignment can work for small-scale tests.

Targeted access and internal testing

Flags let you give access to specific users before a public release. You can enable a feature for your internal team, a group of beta testers, or a specific customer. This is useful for dogfooding (using your own product), for gathering feedback, and for testing with real data in production without exposing the feature to everyone.

Targeting can be based on email domain, user ID, plan type, or any attribute you have. For example, you might roll out a new dashboard to all users on a premium plan first, or to users in a certain region. This is also useful for compliance: if a feature must be disabled in a particular country due to legal reasons, a flag can enforce that rule at runtime.

How to choose the right flag approach

There is no one-size-fits-all flag system. For a small project, a simple JSON file with a few booleans might be enough. For a large organization, you need a dedicated feature-management service with audit logs, permissions, and SDKs. The right choice depends on your team size, your deployment frequency, and your need for speed.

Consider the following factors when choosing:

  • Number of flags: If you have more than a few dozen, you need a way to organize and search them.
  • Audience: Who will flip the flags? Developers, product managers, or support staff? The tool should match their technical skill.
  • Speed: How quickly do you need a flag change to take effect? Some systems update in milliseconds, others take minutes.
  • Audit trail: Do you need to know who changed what and when? For regulated industries, this is essential.
  • Cost: Open-source libraries are free, but managed services charge per seat or per request.

Common pitfalls and how to avoid them

The biggest risk with feature flags is flag debt: old flags that are never removed. Dead flags accumulate in code, making it harder to read and test. They also create hidden states that can cause bugs. To avoid this, treat flags like any other code: they need a review, a test, and a removal plan.

Another pitfall is using flags for too many purposes. A flag that controls both a rollout and an experiment can lead to confusing behavior. Keep flags single-purpose and give them clear names. Also, be careful with flags that wrap critical security checks. If a flag disables authentication, a misconfiguration could expose your system. Always have a default that is safe, and test the flag in both states.

Finally, remember that flags add complexity to your codebase. Every flag is an extra branch, and every branch needs to be tested. Use them where they provide real value, and remove them as soon as they are no longer needed.

Comparing flags to other release strategies

Feature flags are not the only way to manage releases. Dark launches (deploying code that is not yet visible), branch by abstraction, and environment-specific builds are alternatives. Flags are more flexible than environment variables because they can be changed at runtime without a redeploy. They are also more granular than a blue-green deployment, which switches entire environments.

However, flags are not a substitute for good deployment practices. You still need CI/CD, automated testing, and monitoring. Flags complement these tools by giving you fine-grained control over what users see. In a microservices architecture, flags can be particularly powerful because they let you coordinate behavior across services without a coordinated deploy.

Costs and operational overhead

Adopting feature flags has a cost. You need to store flag configurations, evaluate them efficiently, and provide a UI for managing them. If you build your own system, you must handle caching, consistency, and failure modes. If you use a commercial service, you pay a subscription and must trust a third party with a piece of your runtime.

There is also a cognitive cost. Every flag adds a branching path that developers must understand. Overusing flags can make code hard to follow and test. To mitigate this, keep flags short-lived, document their purpose, and schedule regular cleanup. A good rule of thumb is to remove a flag within a few weeks of its final rollout.

Frequently Asked Questions

Can feature flags be used in mobile apps? Yes, but with a caveat. Mobile apps cannot fetch a new flag value instantly because the app is not always connected. You need to fetch flag values at startup and periodically, and accept that there will be a delay. Some services support real-time updates via push notifications, but the app must be designed to handle them.

Do feature flags slow down my application? The performance impact is usually negligible if you evaluate flags locally with a cached value. The main cost is a network call to fetch the flag configuration, which you can do once at startup. In high-throughput systems, you can cache the flag values and update them asynchronously.

How do I test code with feature flags? You should test the code in both states: flag on and flag off. Use a test framework that lets you set flag values in the test environment. Also, write tests that simulate the transition between states, because that is where bugs often appear.

What is the difference between a feature flag and a config file? A config file is static and requires a restart to take effect. A feature flag is dynamic and can be changed at runtime. Config files are fine for settings that rarely change, but flags are better for anything you might want to adjust without a deploy.

Should I use feature flags for every change? No. Flags add complexity, so use them only when you need the flexibility. For trivial changes that are safe to deploy, a simple release is fine. Reserve flags for changes that are risky, need gradual rollout, or involve experimentation.

How do I remove a feature flag safely? First, ensure the flag is set to the desired state for all users. Then, delete the conditional code and the flag definition. Finally, clean up any references in your configuration. Do this in a separate pull request so it is easy to review and revert if needed.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →