← All skills

Feature Flag Exit

Ship behind a flag with the removal already written down, so the flag does not quietly become a permanent fork in the code.

shippingflagsrolloutmaintenanceminutes

When to reach for it

At the moment you type the first `if` around the new behaviour — before there are two code paths and no plan for ever having one again.

What changes

  • Every new flag arrives with an owner, a review date and the written condition that ends it, so removal is scheduled rather than hoped for.
  • Both paths are run before the flag ships, so the off path — which is your rollback — is not discovered broken during an incident.
  • The flag is resolved at one point and passed down, instead of the same key being read in eight places that can disagree inside one request.
  • The cleanup surface is listed while it is fresh: the files, the tests, the config entry, the alert — so removal is a small known change, not archaeology.
  • On the date, the flag is either deleted or has one line saying why it still exists, which stops the slow accumulation of dead branches nobody dares touch.

Pairs with

SKILL.mdpaste into your agent

Feature Flag Exit

A flag is a loan. Write the repayment terms at the moment you take it out, because you will never feel more like writing them than now.

1. Say which kind of flag this is

The kind decides how long it may live:

  • Release gate — off until the feature is ready. Dies at full rollout.
  • Kill switch — on, turned off only in trouble. Lives as long as the risk does, and gets reviewed on a date.
  • Experiment — dies when the experiment concludes, whichever way the result goes.
  • Permission or plan entitlement — not a flag at all. Put it in the permission system, where it can be audited.

2. Write the exit before you write the branch

Three things, recorded with the flag: who owns it, the date it gets reviewed, and the condition that ends it — "removed once every account has run on it for two weeks with no rollback".

3. Read it once

Resolve the flag at a boundary — request start, job start, app boot — and pass the result down. One read point means two states to reason about. Eight read points mean the same key can contradict itself in the middle of one request.

4. Run both paths before shipping

Run the tests, and the app itself, with the flag both ways. The off path is your rollback; a rollback into a branch nobody has executed is not a rollback, it is a second deploy under pressure.

5. Write down the cleanup surface

While it is fresh, list what removal will touch: the files holding the branch, the tests pinning both paths, the config entry, the dashboard or alert that mentions it. That list is what turns removal into an afternoon instead of an excavation.

6. Roll out in steps you record

Move in stages with dates — internal, a small share, everyone. The record is what later tells you the flag has earned its retirement.

7. On the date, remove it

Delete the flag, the branch that lost, the tests for the dead path, the config entry and the alert. If it has to stay, write one line saying why and set the next date.

Rules

  • Do not create a flag with no owner and no date. That is how a temporary branch becomes permanent architecture.
  • Do not let one flag mean two different things in two places.
  • Do not use a flag as a settings knob. If it is meant to stay configurable, it is configuration, and it needs a name and a document.
  • Do not keep the old path after the flag is gone. Code that never runs is not a safety net; it is a false claim about what is tested.
  • Do not nest flags. Two flags on one path is four behaviours, and you will have tested two of them.