CI/CD and DevOps path · Release · Topic 9 of 13

Feature flags vs branches

Not started

A feature flag is a runtime switch around a piece of behaviour. It lets you deploy code that is switched off, turn it on for staff, then 5% of users, then everyone, and turn it off again without a deploy. That separates two things that branches tie together: **integrating** code with everyone else's, and **releasing** a feature to users.

Why it matters: Long-lived feature branches are the usual reason a team can't integrate continuously. Flags let unfinished work live on main, switched off, and let you turn a bad feature off without a deploy.

  1. 1Deploy is not release

    Code can be in production for weeks before anyone sees it. Turning it on becomes a configuration change you can make, and undo, in seconds.

  2. 2Branches delay integration

    A feature branch keeps work apart from everyone else's until the end. A flag keeps it apart from users while it is integrated every day.

  3. 3Flags have kinds

    Release toggles are short-lived. Experiment, ops (kill switch) and permission flags may live longer, and should be named and owned as such.

  4. 4Flags are debt

    Every flag doubles the paths through some code. Give each one an owner and an expiry, and delete it once the rollout is done.

1

How it works

The explanation, with examples you can run.

Branches vs flags

With a feature branch, the work stays out of main until it's done. That keeps users safe from half-built features, but it also keeps the code away from everyone else's changes, so merge pain and surprises pile up at the end. With a flag, the work is merged to main in small steps every day and deployed, but the code path stays dark until the flag is turned on. Integration happens continuously; release happens when you choose.

⌘/Ctrl + Enter
OutputNot run yet

Press Run to see what your code prints, in order.

Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.

Hashing the user ID means each user gets the same answer every time, so nobody flips between old and new checkout on each page load.

Kinds of flags

Pete Hodgson's taxonomy is a useful habit:

  • Release toggles hide unfinished work. They should live days or weeks.
  • Experiment toggles split users for A/B tests; they last as long as the experiment.
  • Ops toggles are kill switches and load-shedding controls for risky features. Some stay for good.
  • Permission toggles turn features on for some customers, such as a paid tier or a beta group.

Naming flags by kind makes it clear which ones are supposed to disappear.

Using flags well

  • Default to off, and make the code safe if the flag service is unreachable (fall back to the default).
  • Keep the check at the edge of the feature, in as few places as possible, not scattered through the code.
  • Test both states in CI for flags that are currently rolling out.
  • Log flag decisions with requests so you can tell whether an incident lines up with a flag change.
  • Give every flag an owner and an expiry date; delete the flag and the dead branch once a rollout is complete.

Flags don't replace good deploy practice: database changes and API contracts still need to be backward compatible, because both flag states run against the same data.

2

Check yourself

3 questions. Get them all right to finish this topic.

  1. 1.A feature is half built. Which approach keeps continuous integration?
  2. 2.The new recommendation service is overloading the database. What does a kill-switch flag give you?
  3. 3.Why should release flags be removed after the rollout?

0 of 3 right so far. Get all three to finish this topic.