Feature flag standard
A comprehensive standard for managing feature flags, covering types, naming conventions, implementation techniques, and best practices.
Standard for managing feature flags, incorporating insights from various sources:
- Martin Fowler: Feature Toggles
- Unleash: Feature Flag Best Practices
- Configu: 8 Feature Flags Best Practices
Introduction
Feature flags, also known as feature toggles, enable teams to deploy new features to production in a controlled manner. This standard outlines the best practices for implementing, managing, and retiring feature flags.
Types of feature flags
- Release Flags: Gradually roll out new features to users.
- Example: Releasing a new shopping checkout flow incrementally to 10% of users.
- Experiment Flags: A/B testing different variations of a feature.
- Example: Testing different feed algorithms to see which increases engagement.
- Operational Flags: Manage system operations like feature throttling.
- Example: Routing transactions through alternative payment gateways during downtime.
- Permission Flags: Control access to features based on user roles or subscriptions.
- Example: Granting access to premium features only to subscribed users.
Naming conventions
Use clear, descriptive names that indicate the purpose of the flag. Prefix flags with their type:
release_newCheckoutFlowexperiment_UIVariantAoperational_enableLoggingpermission_premiumFeature
Implementation techniques
Conditional statements
Using if-else statements in the codebase:
package main import "fmt" func isFlagEnabled(flagName string) bool { // Logic to retrieve flag state return true } func main() { if isFlagEnabled("MY_FEATURE_FLAG") { fmt.Println("Feature enabled") } else { fmt.Println("Feature disabled") } }
Configuration files
Storing feature flag configurations in external files (.env):
package main import ( "fmt" "os" ) func isFlagEnabled(flagName string) bool { return os.Getenv(flagName) == "true" } func main() { if isFlagEnabled("MY_FEATURE_FLAG") { fmt.Println("Feature enabled") } else { fmt.Println("Feature disabled") } }
Database flags
Storing feature flag states in a database table:
| FlagName | IsEnabled |
|---|---|
| release_newCheckoutFlow | true |
| experiment_UIVariantA | false |
| operational_enableLogging | true |
| permission_premiumFeature | true |
Feature flag platforms
Specialized services like:
SDKs and libraries
- Ruby: flipper
- Golang: go-feature-flag
- Java: Split SDK
Best practices
-
Management and Visibility: Use a centralized system for managing feature flags. Make status visible to support and analytics teams.
-
Progressive Rollout: Roll out progressively: internal testing → small group → full rollout. Monitor key metrics at each stage. Use canary releases.
-
Rollback Strategy: Plan for rollback scenarios. Implement quick revert without affecting user experience. Conduct regular drills.
-
Documentation: Document flag usage, purpose, state, and impact. Communicate changes to all relevant teams.
-
Performance: Avoid excessive feature flags. Cache flag states outside loops. Monitor performance impact.
-
Security: Ensure flags don't expose PII. Implement least privilege access. Conduct regular audits.
-
Avoiding Complexity: Avoid dependencies between flags. Implement clean feature switches over excessive code branching.
-
Retiring Flags: Plan removal of obsolete flags to avoid technical debt. Schedule cleanup as part of the release cycle.
-
Testing: Test flags in different environments. Validate behavior under various conditions. Use A/B testing to compare impact.