Skip to content

Feature Flag Implementation

Wrapping new behaviour so rollback is one switch — and so trunk can carry unfinished work without exposing it. Both flag-on and flag-off paths are tested; the flag's removal date is named at creation.

Owners: Developer Phase it lives in: How We Build (Volume IV) The corpus principle this enacts: Rollback possible is not. A confirmed time is.

Where it lives in the chain

How to do this

  • Convention — every flag has: a name (grading.shortcut-submit), a default (false), an owner, and a removal date at creation.
  • Convention — both paths (flag on, flag off) are tested. If the flag-off path goes untested, the rollback is theatre.
  • Related craftFlag Lifecycle — birth → cleanup

What good implementation looks like

ts
if (flags.enabled('grading.shortcut-submit', { user })) {
  return submitWithShortcut(exam)
}
return submitClassic(exam)

The two paths are clearly named. The flag-off path stays maintained until the flag is removed. The PR that adds the flag also adds the removal task to the backlog with a date. A flag created without a removal date is technical debt born already due.

The discipline: flags carry the rollout for days or weeks, not months. A flag still wrapping behaviour six months after launch is no longer a flag — it is a permanent branch in the code with a switch nobody flips. The PR that removes the flag is as important as the PR that added it.

200apps · How We Work · NWIRE