Feature Flag Management | Safe Releases
Decouple deployment from release with feature flags. Enable gradual rollouts, instant rollbacks, and A/B testing. Remove flags 2-4 weeks after full rollout.
6 min read
Feature flags decouple deployment from release. Deploy code when ready, release features when confident. This enables safer rollouts, easier rollbacks, and better testing. This guide covers practical approaches to feature flag management.
Flag Types
| Type | Purpose | Lifespan |
|---|---|---|
| Release | Gradual rollout | Short |
| Experiment | A/B testing | Medium |
| Ops | Kill switch | Long |
| Permission | Customer features | Permanent |
Basic Implementation
Simple Feature Flags
FEATURE FLAG BASICS
βββββββββββββββββββ
SIMPLE IMPLEMENTATION:
βββββββββββββββββββββββββββββββββββββ
Basic flag check:
// Configuration
const FLAGS = {
newCheckout: true,
darkMode: false,
betaFeatures: true,
};
// Usage
if (FLAGS.newCheckout) {
return <NewCheckoutFlow />;
} else {
return <OldCheckoutFlow />;
}
EXTERNAL CONFIGURATION:
βββββββββββββββββββββββββββββββββββββ
Flags from server:
// Fetch flags at startup
const flags = await fetchFlags(userId);
// Usage
if (flags.isEnabled('newCheckout')) {
return <NewCheckoutFlow />;
}
// Benefits:
// - Change without deploy
// - User-specific flags
// - Percentage rollouts
// - Analytics built-in
FLAG SERVICE PROVIDERS:
βββββββββββββββββββββββββββββββββββββ
Popular services:
βββ LaunchDarkly
βββ Split.io
βββ ConfigCat
βββ Unleash (open source)
βββ Flagsmith (open source)
βββ Choose based on needs
Rollout Strategies
Gradual Release
ROLLOUT STRATEGIES
ββββββββββββββββββ
PERCENTAGE ROLLOUT:
βββββββββββββββββββββββββββββββββββββ
Gradual increase:
Day 1: 1% of users
βββ Monitor for errors
βββ Check performance
βββ Watch metrics
βββ Small blast radius
Day 2: 10% of users
βββ More traffic
βββ More confident
βββ Still controlled
βββ Easy rollback
Day 3: 50% of users
βββ Half traffic
βββ Significant validation
βββ Almost there
βββ Ready for full?
Day 4: 100% of users
βββ Full rollout
βββ Feature live
βββ Flag can be removed
βββ Done!
TARGETED ROLLOUT:
βββββββββββββββββββββββββββββββββββββ
Specific users first:
βββ Internal employees first
βββ Then beta users
βββ Then percentage of all
βββ Then full release
βββ Staged confidence building
// Targeting rules
flag.targets = [
{ type: 'email', contains: '@company.com' }, // Staff
{ type: 'segment', equals: 'beta_users' }, // Beta
{ type: 'percentage', value: 10 }, // 10%
];
CANARY RELEASE:
βββββββββββββββββββββββββββββββββββββ
βββ Combine with deployment canary
βββ Flag enables on canary instances
βββ Double safety net
βββ Very controlled
βββ Maximum safety
Flag Lifecycle
Creation to Removal
FEATURE FLAG LIFECYCLE
ββββββββββββββββββββββ
CREATION:
βββββββββββββββββββββββββββββββββββββ
When creating flag:
βββ Name: descriptive, consistent
βββ Owner: who's responsible
βββ Purpose: why this flag exists
βββ Expiry: when should it be removed
βββ Tracking: link to task/issue
βββ Document the flag
Example:
{
name: "new_checkout_v2",
owner: "sarah@company.com",
purpose: "Gradual rollout of checkout redesign",
created: "2024-01-15",
expectedRemoval: "2024-02-15",
jiraTicket: "PROJ-456"
}
ACTIVE USE:
βββββββββββββββββββββββββββββββββββββ
While flag is active:
βββ Monitor usage
βββ Track in project management
βββ Update status as rollout progresses
βββ Document decisions
βββ Active management
REMOVAL:
βββββββββββββββββββββββββββββββββββββ
When feature stable:
1. Flag at 100% for 2+ weeks
2. No issues observed
3. Remove flag code
4. Deploy code cleanup
5. Delete flag from service
6. Close tracking task
CLEANUP DEBT:
βββββββββββββββββββββββββββββββββββββ
Schedule regular audits:
βββ What flags are active?
βββ Any past expected removal?
βββ Any orphaned flags?
βββ Remove stale flags
βββ Prevent accumulation
βββ Monthly or quarterly audit
Flag Hygiene
Avoiding Flag Debt
FLAG HYGIENE
ββββββββββββ
FLAG DEBT SYMPTOMS:
βββββββββββββββββββββββββββββββββββββ
Warning signs:
βββ Too many active flags
βββ Nobody knows what flags do
βββ Flags never removed
βββ Complex flag combinations
βββ Flags from years ago
βββ Nobody owns flags
βββ Technical debt
PREVENTION:
βββββββββββββββββββββββββββββββββββββ
Good practices:
βββ Expiry dates on creation
βββ Owner for every flag
βββ Task to remove flag
βββ Regular audits
βββ Limit total flags
βββ Culture of cleanup
βββ Flags are temporary
FLAG LIMITS:
βββββββββββββββββββββββββββββββββββββ
Guidelines:
βββ Max 10-20 active release flags
βββ More for ops/permission flags
βββ If too many, stop adding
βββ Clean up before creating new
βββ Quality over quantity
AUDIT PROCESS:
βββββββββββββββββββββββββββββββββββββ
Monthly:
βββ List all active flags
βββ Check each: still needed?
βββ Create removal tasks
βββ Remove expired flags
βββ Update documentation
βββ Regular maintenance
Testing
Flag Testing Strategies
TESTING WITH FLAGS
ββββββββββββββββββ
TEST BOTH PATHS:
βββββββββββββββββββββββββββββββββββββ
When flag exists:
βββ Test with flag ON
βββ Test with flag OFF
βββ Both paths work
βββ CI tests both
βββ No surprises
describe('Checkout', () => {
it('works with new checkout (flag on)', () => {
setFlag('newCheckout', true);
// test new path
});
it('works with old checkout (flag off)', () => {
setFlag('newCheckout', false);
// test old path
});
});
ENVIRONMENT FLAGS:
βββββββββββββββββββββββββββββββββββββ
Different per environment:
βββ Dev: All flags on (test new)
βββ Staging: Production mirror
βββ Production: Controlled rollout
βββ Environment-specific config
TESTING IN PRODUCTION:
βββββββββββββββββββββββββββββββββββββ
Flag enables safe testing:
βββ Enable for internal users
βββ Test in production
βββ Real data, real conditions
βββ Flag protects users
βββ Build confidence
βββ Then rollout
Project Integration
Tracking Flags in GitScrum
GITSCRUM FLAG TRACKING
ββββββββββββββββββββββ
FLAG AS TASK:
βββββββββββββββββββββββββββββββββββββ
Create task for flag:
βββ "Remove new_checkout_v2 flag"
βββ Due date: 2 weeks after full rollout
βββ Assigned: Flag owner
βββ Label: "flag-cleanup"
βββ Tracked in backlog
βββ Won't forget
FLAG STATUS:
βββββββββββββββββββββββββββββββββββββ
Track rollout status:
βββ In task: current percentage
βββ In task: any issues
βββ Update as rollout progresses
βββ Stakeholder visibility
βββ Progress tracked
FLAG DOCUMENTATION:
βββββββββββββββββββββββββββββββββββββ
In NoteVault:
βββ Active flags list
βββ Flag purposes
βββ Rollout status
βββ Cleanup schedule
βββ Single reference
βββ Team visibility
RELEASE NOTES:
βββββββββββββββββββββββββββββββββββββ
When flag fully rolled out:
βββ Feature now in release notes
βββ Linked to original feature task
βββ Flag cleanup task created
βββ Complete tracking
Best Practices
For Feature Flags
Anti-Patterns
FLAG MANAGEMENT MISTAKES:
β Flags without owners
β Flags never removed
β Too many active flags
β No expiry dates
β Complex flag combinations
β Flags as permanent features
β No documentation
β No testing of both paths