Why naming flags well matters
A project without a convention ends up with flags like NEW_FLOW_2,
fix_thing and tmp_test_remove. Three months later nobody knows
what they do. Naming with discipline makes every flag readable even after the original
author is gone.
Pete Hodgson's four types
The most-used framework splits flags into four buckets: Release (hide work in progress), Experiment (A/B testing), Ops (kill switches, throttling), Permission (access by plan or role). Each has different life cycle and cleanup criteria.
Recommended structure
<type>.<area>.<short-description>. Examples:
release.checkout.new-payment-flow,
experiment.search.relevance-v2,
ops.queue.disable-batching,
permission.billing.beta-pricing.
Case convention
dot.case is popular in LaunchDarkly and Flagsmith. kebab-case in config files. SCREAMING_SNAKE_CASE is typical for flags as env vars. camelCase appears in JS configs. Rule: one convention per project, whichever you pick.
What to avoid
- Negative names:
disable_old_checkoutforces inverted thinking. - Generic names:
new_thing,fix. - Author initials:
jp_test. - Tickets only:
JIRA-1234. The reader won't open the ticket.
The cleanup plan
Every flag should be born with an end date. Release: removed after successful 100% rollout. Experiment: after the decision and posting results. Ops: may live indefinitely. Permission: live as long as the feature exists.
Audit with tags
Platforms like LaunchDarkly and Unleash let you tag flags with owner, team, creation ticket and expected removal date. Once a quarter, an audit lists flags older than N days: either remove them or document why they're still alive.
Naming collisions
If your product has multiple sub-teams, prefix with the business unit:
web.checkout.flow-v2, mobile.checkout.flow-v2. Flags shared
across frontend and backend should have identical names so cross-stack debugging is
trivial.