Skip to main content
Deployments

Feature flags done right: patterns that do not become permanent debt

Feature flags make releases safer only when their owners, audiences, rollback paths, and deletion dates are explicit. Ship narrow, observable flags—not a second configuration system.

Thien Nguyen
By Thien Nguyen
Updated June 30, 2026 · 2 min read

A flag is a runtime branch with operational consequences. It can save a launch—or create two applications nobody knows how to test. The difference is discipline, not the flag provider.

Short answer: every flag needs an owner, a precise audience, a default-safe state, telemetry for both branches, and an expiry date. Release flags should be deleted after rollout; entitlement and kill-switch flags are different species and deserve different rules.

Name the job before naming the flag

Flag typeExampleLifetime
Releasenew_checkout to 5% of usersDays or weeks
Kill switchDisable a costly AI callPotentially long-lived
ExperimentCompare two onboarding flowsUntil decision is made
EntitlementEnterprise-only exportProduct lifetime

Treating every flag as a permanent boolean is how if (flags.foo) spreads into thirty files with no one willing to delete it.

Roll out by evidence, not vibes

if (flags.enabled("new_checkout", { userId, plan })) {
  return checkoutV2(request);
}
return checkoutV1(request);

Start with internal accounts, then a small stable cohort, then a wider percentage. Track the user-visible metric and the failure metric for both paths. A flag with no metric answers only “did we turn it on?”, which is not enough.

A flag is not a substitute for a migration plan. If the new path writes data the old path cannot read, the flag merely lets you choose when to break compatibility.

The deletion checklist

  1. Set the winning behaviour as the code default.
  2. Remove the losing branch and tests that only supported it.
  3. Delete the flag definition and dashboard targeting.
  4. Verify no clients cache an old value that changes safety behaviour.

The best feature-flag dashboard has a shrinking list. If a team cannot state the removal date at creation time, it is probably configuration or an entitlement—model it that way instead.

Cover photo by Nik Oak on Pexels.

References

Primary documentation and specifications checked when this article was last updated.

DeploymentsProduct EngineeringReliability

Related articles

All articles