Martin Fowler identifies four categories of feature flags, each with different lifecycle and management characteristics. Release flags control the rollout of incomplete or new features -- they are temporary and should be removed after full rollout. Experiment flags support A/B testing -- they route users to different variants and are removed after the experiment concludes. Ops flags provide operational control -- circuit breakers, performance mode toggles, maintenance mode switches -- and may be permanent. Permission flags gate features based on user entitlements -- premium features, beta access, regional availability -- and are part of the business logic.
The distinction matters for lifecycle management. Release flags that are not removed become dead code that confuses future developers. A codebase with 200 stale feature flags -- checks for features that have been fully rolled out for months -- is harder to understand and maintain. Set an expiration date on every release flag at creation time and alert when flags exceed their expected lifetime. LaunchDarkly, Unleash, and Flagsmith all support flag expiration metadata.
Ops flags require different governance than release flags because they affect system behavior in production. Changing an ops flag -- disabling a feature to reduce load during an incident, switching traffic between backend implementations -- should be auditable, reversible, and restricted to authorized team members. Treat ops flags with the same rigor as infrastructure configuration changes.
The simplest feature flag is a boolean check in application code: if flag is enabled, execute new code path, otherwise execute old code path. This works for simple on/off toggles but becomes unwieldy for progressive rollouts and experiments. A proper feature flag system evaluates rules based on user attributes -- user ID, email domain, geographic location, account tier -- to determine which users see which variant.
Server-side evaluation is more secure than client-side evaluation because flag rules and targeting criteria remain on the server. The client receives only the evaluation result, not the rules themselves. This prevents users from inspecting flag configurations and manipulating their targeting. Client-side SDKs from LaunchDarkly and similar platforms cache flag evaluations locally and stream updates in real-time, providing fast evaluation without exposing the underlying rules.
Implement flags at the API layer rather than the UI layer when possible. A flag in the API response -- including or excluding a field, returning different data structures, enabling or disabling an endpoint -- is invisible to the client implementation. This separation means the same flag controls both web and mobile clients without requiring flag checks in each client codebase. The UI renders whatever the API provides, and the API decides what to provide based on the flag evaluation.
Percentage-based rollout is the most common progressive release strategy. Start by enabling the feature for 1% of users, monitor error rates and performance metrics, then gradually increase to 5%, 25%, 50%, and 100%. Each increase should be followed by a monitoring period -- typically 1-4 hours depending on traffic volume -- before proceeding. If metrics degrade at any stage, roll back to the previous percentage instantly by changing the flag configuration.
Ring-based deployment adds organizational targeting to percentage rollouts. Ring 0 is the engineering team. Ring 1 is internal employees. Ring 2 is beta customers who opted in. Ring 3 is a percentage of general users. Ring 4 is all users. Each ring provides feedback at a different scale and with different risk tolerance. Microsoft uses this ring-based model for Office 365 and Windows updates, catching issues in each ring before exposing them to the broader population.
Geographic rollouts control risk for global products. Launch in one region first -- typically the team's own region where debugging is easiest -- then expand region by region. This strategy is particularly important for features that depend on external services, payment providers, or regulatory compliance that varies by region. Uber uses geographic rollouts for major feature changes, often launching in a single city before expanding nationwide.
Every feature flag should have associated monitoring that answers: is this feature working correctly for the users who have it? Define success metrics (conversion rate, task completion rate) and guardrail metrics (error rate, latency, crash rate) before the rollout begins. If guardrail metrics degrade beyond a threshold -- a 2x increase in error rate, a 20% increase in p99 latency -- automatically roll back the flag.
Automated rollback based on metric thresholds is safer than relying on human monitoring. A degradation that starts at 2 AM will continue affecting users until someone notices and acts. An automated system reverts the flag within minutes of threshold breach. LaunchDarkly's metric-based targeting and custom automation via their API enable this automated rollback pattern. Build the automation during flag setup, not after an incident demonstrates the need.
Log flag evaluations alongside application events for debugging. When investigating an issue, being able to determine which flags were active for the affected user at the time of the incident is essential for root cause analysis. Include the flag evaluation results in the request context so they appear in application logs and distributed traces. This correlation between flag state and application behavior is the diagnostic tool that makes progressive rollouts debuggable.
Feature flags are intentional technical debt -- each flag adds a branch to the code that increases testing complexity and cognitive load. A function with three active flags has eight possible execution paths (2^3). Keeping the number of active flags low is essential for maintainability. Target fewer than 20 active release flags at any time for most teams. Larger organizations like Google and Facebook manage thousands of flags, but they have dedicated infrastructure and tooling to handle that complexity.
Remove flags promptly after full rollout or experiment conclusion. Create a calendar reminder or automated alert when a flag reaches its expiration date. The removal process should be treated as regular maintenance work -- scheduled in sprints, reviewed in pull requests, and tracked like any other task. Some teams designate one day per month as flag cleanup day, where the sole focus is removing expired flags and simplifying the associated code.
Test both sides of every flag. If the flag is on for 5% of users, 95% of users are running the old code path. If the flag is off for everyone after a rollback, 100% of users are running the old path. Both paths must work correctly, which means both paths need test coverage. Flagged code that is never tested in the off state creates latent bugs that surface during rollbacks -- exactly when the team can least afford additional problems.
Part of our complete guide: MVP Scoping & Product Development →
This article is part of our comprehensive knowledge hub on mvp scoping & product development. Read the full guide for a complete strategic framework.
Our team helps companies implement the frameworks and strategies covered in this article.
Get in Touch