Engineering Practice
Feature flags: ship dark, ramp, and retire
Reading about flags is not the same as living the full lifecycle. Build a small flagged service, ship a feature dark, ramp it by sticky percentage with a kill-switch ready, then do the part most teams skip — retire the flag and delete its dead branch — proving each step with evidence.
Turn the unit’s mental model into a reproducible loop: deploy dark, roll out sticky, kill-switch on demand, and run a flag through its full lifecycle to retirement — so the discipline that prevents flag debt becomes muscle memory.
Build a small HTTP service with a minimal feature-flag layer, ship one feature dark, ramp it through a sticky percentage rollout with a working kill-switch, then run the full retirement lifecycle — proving deploy/release decoupling, stickiness, fail-open evaluation, and clean removal with evidence at each step.
- A rollout log/table showing served fraction at 1/5/25/100% matching the target, plus evidence that a fixed sample of users stayed on one variant across requests (proving stickiness, not per-call randomness).
- A kill-switch demonstration: the subsystem turns off within seconds of the toggle, and a forced flag-source outage shows the service still serving on last-known config rather than erroring (fail-open verified, not assumed).
- A flag registry entry per flag with type, owner, and the release flag's expiry/removal ticket.
- A diff (or PR) that removes the release flag and its dead branch, with a grep/search showing zero remaining references and the cleanup ticket closed — the lifecycle completed, not left at 100%.
- Add layered/attribute targeting rules (plan == enterprise, betaOptIn == true, then a sticky rollout) and demonstrate first-match short-circuit precedence with test cases.
- Add a stale-flag detector: a script that lists flags serving the same value for over ~30 days and skips those typed as permanent ops/kill-switch — your own Piranha-lite.
- Add a CI gate that fails the build when a release flag is past its expiry date or has no removal ticket, so flag debt cannot accumulate silently.
- Add metrics-driven auto-halt: wire the rollout to read error rate and automatically flip the flag off if a ramp step breaches a threshold, then write up how this turns rollback from a human decision into a guardrail.
This is the loop you run on every flagged release: deploy dark so deploy and release are separate events, roll out sticky by a stable hash so users do not flicker, keep a kill-switch wired against local config with a safe default so the flag source is never a hard dependency, type every flag with an owner and an expiry, and complete the lifecycle by deleting the release flag and its dead branch at 100%. Doing it once end-to-end on a toy service makes the production discipline — the discipline that would have saved Knight Capital — automatic.