Feature Flags in GitScrum | Track Rollouts
Track feature flag status in GitScrum tasks. Coordinate gradual rollouts, A/B tests, and kill switches. Clean up flags after full release to avoid debt.
8 min read
Feature flags decouple deployment from release. GitScrum helps teams track flag-controlled features and coordinate rollouts effectively.
Feature Flag Basics
What Flags Enable
FEATURE FLAG USE CASES:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β GRADUAL ROLLOUT: β
β Deploy to 1% β 10% β 50% β 100% β
β Monitor metrics at each stage β
β Roll back instantly if issues β
β β
β DARK LAUNCHING: β
β Code deployed but hidden from users β
β Enables integration testing in production β
β No risk to users β
β β
β A/B TESTING: β
β 50% see version A, 50% see version B β
β Measure which performs better β
β Data-driven decisions β
β β
β KILL SWITCH: β
β Disable problematic feature instantly β
β No deployment needed β
β Minutes vs hours to respond β
β β
β BETA ACCESS: β
β Enable for specific users/customers β
β Gather feedback before wide release β
β Premium feature access control β
β β
β OPERATIONAL CONTROLS: β
β Enable/disable expensive features under load β
β Graceful degradation β
β Circuit breakers β
β β
β TRUNK-BASED DEVELOPMENT: β
β Incomplete features behind flags β
β Merge to main frequently β
β No long-lived feature branches β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Flag Types
Categorizing Flags
FEATURE FLAG TYPES:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β RELEASE FLAGS (Short-lived): β
β βββββββββββββββββββββββββββββ β
β Purpose: Control new feature rollout β
β Lifespan: Days to weeks β
β Example: new_dashboard_enabled β
β β
β Create β Rollout β Remove β
β MUST be removed after 100% rollout β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β EXPERIMENT FLAGS (Short-lived): β
β βββββββββββββββββββββββββββββββ β
β Purpose: A/B testing β
β Lifespan: Duration of experiment β
β Example: checkout_flow_experiment β
β β
β Create β Run experiment β Pick winner β Remove β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β PERMISSION FLAGS (Long-lived): β
β ββββββββββββββββββββββββββββββ β
β Purpose: Entitlement/feature access β
β Lifespan: Permanent or product lifecycle β
β Example: premium_analytics_enabled β
β β
β These are essentially product features β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β OPERATIONAL FLAGS (Long-lived): β
β ββββββββββββββββββββββββββββββββ β
β Purpose: System behavior control β
β Lifespan: Permanent β
β Example: enable_caching, rate_limit_mode β
β β
β Used for ops, not features β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Flag Lifecycle
Creating Flags
FLAG CREATION WORKFLOW:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β WHEN TO CREATE FLAG: β
β β
β During development: β
β β’ New user-facing feature β
β β’ Risky change β
β β’ Cross-team dependency β
β β’ Feature needing gradual rollout β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β FLAG NAMING CONVENTION: β
β β
β Format: [scope]_[feature]_[type] β
β β
β Examples: β
β β’ dashboard_new_charts_release β
β β’ checkout_one_click_experiment β
β β’ premium_analytics_permission β
β β’ cache_disable_operational β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β GITSCRUM TASK: β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β PROJ-123: New Dashboard Charts ββ
β β ββ
β β Feature Flag: ββ
β β Name: dashboard_new_charts_release ββ
β β Type: Release flag ββ
β β Created: 2024-01-15 ββ
β β Owner: @alex ββ
β β Cleanup due: 2024-02-15 ββ
β β ββ
β β Rollout plan: ββ
β β β 5% - Internal testing ββ
β β β 20% - Beta customers ββ
β β β 50% - General availability ββ
β β β 100% - Full rollout ββ
β β β Remove flag (cleanup) ββ
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Rollout Process
FEATURE ROLLOUT STAGES:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β STAGE 1: INTERNAL (0%) β
β βββββββββββββββββββββ β
β Flag: OFF by default β
β Access: Enabled for internal emails only β
β Purpose: QA and internal testing β
β Duration: Until confident β
β β
β STAGE 2: BETA (5-10%) β
β βββββββββββββββββββββ β
β Flag: Enabled for selected customers β
β Access: Opt-in beta users β
β Purpose: Early feedback, bug finding β
β Duration: 1-2 weeks β
β Monitor: Error rates, feedback β
β β
β STAGE 3: GRADUAL (10% β 50%) β
β ββββββββββββββββββββββββββββ β
β Flag: Percentage rollout β
β Access: Random sampling β
β Purpose: Scale testing β
β Duration: Days per stage β
β Monitor: Performance, metrics β
β β
β STAGE 4: GENERAL (50% β 100%) β
β βββββββββββββββββββββββββββββ β
β Flag: Increasing percentage β
β Access: Remaining users β
β Purpose: Full rollout β
β Duration: Days β
β Monitor: All metrics β
β β
β STAGE 5: CLEANUP β
β ββββββββββββββββ β
β Flag: Remove entirely β
β Code: Remove flag checks β
β Purpose: Eliminate tech debt β
β Timeline: Within 30 days of 100% β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Flag Cleanup
Preventing Flag Debt
FEATURE FLAG CLEANUP:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β FLAG DEBT PROBLEM: β
β β
β Week 1: 5 flags β
β Month 1: 15 flags β
β Month 6: 47 flags (half obsolete) β
β Year 1: 100+ flags, nobody knows which are active β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β CLEANUP RULES: β
β β
β 1. SET EXPIRATION AT CREATION β
β Every release flag has cleanup date β
β Default: 30 days after 100% rollout β
β β
β 2. TRACK IN GITSCRUM β
β Cleanup task created with feature β
β Linked to original feature task β
β Assigned to feature owner β
β β
β 3. REGULAR AUDITS β
β Monthly: Review all flags β
β Identify: Flags at 100% for > 30 days β
β Action: Create cleanup tasks β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β CLEANUP TASK: β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β TECH-456: Remove dashboard_new_charts flag ββ
β β ββ
β β Feature: New Dashboard Charts (PROJ-123) ββ
β β Flag at 100% since: 2024-02-01 ββ
β β Cleanup due: 2024-03-01 ββ
β β ββ
β β Tasks: ββ
β β β Remove flag from config ββ
β β β Remove flag checks from code ββ
β β β Delete unused code paths ββ
β β β Update tests ββ
β β β Deploy ββ
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Flag Dashboard
Visibility and Tracking
FEATURE FLAG STATUS OVERVIEW:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FEATURE FLAGS DASHBOARD β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ACTIVE FLAGS: 12 β
β β
β BY STATUS: β
β π’ Rolling out: 3 β
β π‘ At 100%: 4 (need cleanup) β
β π΅ Experiments: 2 β
β βͺ Permanent: 3 β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β FLAG ROLLOUT SINCE ACTION β
β ββββββββββββββββββββββββββββ βββββββββ βββββββ ββββββββ β
β dashboard_new_charts 100% 14 days Cleanup! β
β checkout_redesign 50% 3 days Monitor β
β search_v2 20% 7 days Expand β
β mobile_nav_experiment 50%/50% 5 days Running β
β premium_reports perm - - β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β NEEDS ATTENTION: β
β β
β β οΈ dashboard_new_charts at 100% for 14 days β
β β Create cleanup task β
β β
β β οΈ payment_gateway_v2 at 100% for 45 days β
β β Overdue for cleanup! β
β β
β [View all flags] [Create new flag] [Run audit] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Implementation Patterns
Code Patterns
FEATURE FLAG CODE PATTERNS:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β SIMPLE CHECK: β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β if (featureFlags.isEnabled('new_dashboard')) { ββ
β β return <NewDashboard /> ββ
β β } ββ
β β return <OldDashboard /> ββ
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β WITH CONTEXT: β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β if (featureFlags.isEnabled('premium_feature', { ββ
β β userId: user.id, ββ
β β plan: user.plan ββ
β β })) { ββ
β β // Show premium feature ββ
β β } ββ
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β AVOID: β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β // β Nested flags ββ
β β if (flag1 && flag2 && !flag3) { ... } ββ
β β ββ
β β // β Flags in loops ββ
β β items.map(item => ββ
β β featureFlags.isEnabled('x') ? ... : ... ββ
β β ) ββ
β β ββ
β β // β Late flag check (side effects already happened) ββ
β β processPayment(); ββ
β β if (featureFlags.isEnabled('new_receipt')) { ... } ββ
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β BEST PRACTICES: β
β β’ Check early in request/component β
β β’ Keep flag logic simple β
β β’ Cache flag values per request β
β β’ Log flag evaluations for debugging β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ