• MCP
  • Rules
  • Leaderboard
  • Generate Rule⌘U

Designed and Built by
GrowthX

  • X
  • LinkedIn
    1. Home
    2. Rules
    3. Feature Flag Driven Deployment Rules

    Feature Flag Driven Deployment Rules

    Comprehensive rules for implementing, managing, and governing feature-flag based releases in modern CI/CD pipelines.

    Stop Fear-Based Deployments: Master Feature Flag-Driven Delivery

    You're tired of deployment anxiety. The cold sweat when pushing to production. The weekend war rooms when releases go sideways. What if deploying became as routine as committing code?

    Feature flag-driven deployment transforms your release process from a high-stakes gamble into a controlled, observable operation. Deploy anytime. Release gradually. Roll back instantly. All without touching your CI/CD pipeline.

    The Real Problem: Deployment Isn't the Issue, Release Timing Is

    Traditional deployment models force you to choose between speed and safety. Ship fast and risk breaking production, or batch changes and delay valuable features. This false choice creates several critical pain points:

    Release Bottlenecks: Every deployment becomes a coordinated event requiring multiple teams, perfect timing, and crossed fingers. Features sit in staging for weeks waiting for the "right" deployment window.

    Rollback Complexity: When things go wrong, you're stuck with time-consuming rollbacks, database migrations in reverse, and frustrated users experiencing downtime.

    Testing Limitations: You can't truly test production load, real user behavior, or edge cases until you're live. By then, it's too late to make changes without another deployment cycle.

    Team Coordination Overhead: Product, engineering, and operations teams spend more time coordinating releases than building features. Every change requires cross-team meetings and approval chains.

    The Solution: Decouple Deployment from Release

    Feature flags fundamentally change how you think about shipping code. Instead of deploying features, you deploy capabilities that can be activated independently. This separation gives you unprecedented control over when, how, and to whom features are released.

    Here's what this looks like in practice:

    // Deploy this code anytime - it's dormant until you flip the flag
    export const handleCheckout = async (request: CheckoutRequest) => {
      if (!isEnabled('checkout-release-v2', { userId: request.userId })) {
        return legacyCheckoutProcessor(request);
      }
      
      return newCheckoutProcessor(request);
    };
    

    Your new checkout flow is deployed but completely safe. It won't execute until you decide to enable it, and you can target specific users, percentages, or regions without touching code.

    Key Benefits: Measurable Workflow Improvements

    Deploy 10x More Frequently: Teams using feature flags deploy multiple times per day instead of weekly batches. You can ship incomplete features behind flags, reducing branch conflicts and integration headaches.

    Reduce Incident Response Time by 80%: Instead of rollbacks taking 20-30 minutes, flag toggles happen in seconds. Your mean time to recovery (MTTR) drops from hours to minutes.

    Eliminate Feature Staging Bottlenecks: No more waiting for "the next release window." Features can be developed, tested, and released on independent timelines. A critical bug fix doesn't block an unrelated feature launch.

    Increase Testing Coverage: Run the same codebase with different flag combinations in your CI pipeline. Test both the old and new code paths automatically, catching regressions before they reach production.

    Real Developer Workflows: From Chaos to Control

    Progressive Rollout Workflow

    Instead of shipping to 100% of users immediately, you can control exposure:

    // Start with 5% of users
    const experimentConfig = {
      flagKey: 'search-exp-rankAlgo',
      variations: {
        control: 'legacy_ranking',
        treatment: 'ml_ranking'
      },
      targeting: {
        percentage: 5,
        segments: ['premium_users']
      }
    };
    

    Monitor error rates, performance metrics, and user behavior. If metrics look good, increase to 25%, then 50%, then 100%. If issues arise, instantly roll back to 0% while you investigate.

    Kill Switch Implementation

    Protect critical paths with instant disable capabilities:

    export const processPayment = async (paymentData: PaymentRequest) => {
      // Kill switch for payment processing
      if (!isEnabled('payments-ops-stripe', { region: paymentData.region })) {
        // Fallback to backup processor or queue for later
        return backupPaymentProcessor(paymentData);
      }
      
      return stripePaymentProcessor(paymentData);
    };
    

    When your payment provider has an outage, flip one switch to route all payments to your backup processor. No deployment, no code changes, no downtime.

    A/B Testing Integration

    Run experiments without separate tooling:

    const useRecommendationAlgorithm = () => {
      const variant = useFlag('recommendations-exp-algorithm', 'control');
      
      switch (variant) {
        case 'collaborative':
          return collaborativeFiltering;
        case 'content_based':
          return contentBasedFiltering;
        default:
          return legacyRecommendations;
      }
    };
    

    Your feature flags become your experimentation platform. Measure conversion rates, user engagement, and performance metrics across variants.

    Implementation Guide: Get Started in 30 Minutes

    Step 1: Choose Your Flag Provider

    For enterprise teams: LaunchDarkly offers the most robust feature set with advanced targeting, analytics, and enterprise security.

    For cost-conscious teams: Unleash or Flagsmith provide open-source alternatives you can self-host.

    For rapid prototyping: ConfigCat offers simple APIs and generous free tiers.

    Step 2: Set Up Type-Safe Flag Evaluation

    Create a typed wrapper around your provider's SDK:

    // src/flags/client.ts
    import { LDClient } from 'launchdarkly-node-server-sdk';
    
    export type FlagKey = 
      | 'checkout-release-v2'
      | 'search-exp-rankAlgo'
      | 'payments-ops-stripe'
      | 'auth-kill-jwt';
    
    export type FlagContext = {
      userId?: string;
      email?: string;
      region?: string;
      plan?: string;
    };
    
    export const isEnabled = (
      key: FlagKey, 
      context: FlagContext,
      defaultValue: boolean = false
    ): boolean => {
      return client.variation(key, context, defaultValue);
    };
    

    Step 3: Implement Flag Classification

    Use a naming convention that makes flag purpose obvious:

    • checkout-release-v2 - Release flag for new checkout flow
    • search-exp-rankAlgo - Experimentation flag for A/B testing
    • payments-ops-stripe - Operational flag for service routing
    • auth-kill-jwt - Kill switch for JWT authentication

    Step 4: Add Lifecycle Management

    Set up automated cleanup to prevent flag debt:

    // scripts/flag-inventory.ts
    const flagInventory = async () => {
      const codeFlags = await scanCodebaseForFlags();
      const providerFlags = await fetchProviderFlags();
      
      const staleFlags = providerFlags.filter(flag => 
        !codeFlags.includes(flag.key) && 
        daysSinceCreated(flag) > 90
      );
      
      if (staleFlags.length > 0) {
        console.error(`Found ${staleFlags.length} stale flags. Build failing.`);
        process.exit(1);
      }
    };
    

    Step 5: Integrate with Your CI/CD Pipeline

    Test both flag states in your pipeline:

    # .github/workflows/test.yml
    - name: Test with flags enabled
      run: npm test
      env:
        FEATURE_FLAGS_OVERRIDE: '{"checkout-release-v2": true}'
    
    - name: Test with flags disabled  
      run: npm test
      env:
        FEATURE_FLAGS_OVERRIDE: '{"checkout-release-v2": false}'
    

    Results & Impact: What You'll Achieve

    Deployment Frequency: Teams report going from weekly deploys to multiple daily deploys within the first month.

    Incident Recovery: Mean time to recovery drops from 45 minutes to under 2 minutes for flag-controlled features.

    Feature Lead Time: New features reach production 3-5x faster since they don't wait for deployment windows.

    Testing Coverage: Automated testing of both code paths catches 60% more regressions before production.

    Developer Confidence: Engineers report significantly less anxiety around deployments and feel more empowered to ship features incrementally.

    Business Agility: Product teams can make go/no-go decisions independently of engineering deployment schedules.

    The transformation isn't just technical—it's cultural. Your team will shift from deployment-driven development to feature-driven development. You'll ship with confidence, experiment with safety, and respond to incidents with speed.

    Stop treating deployments as risky events. Start treating them as routine operations that enable controlled, observable feature releases. Your users get better experiences, your team gets better sleep, and your business gets better agility.

    Feature Flags
    TypeScript
    Continuous Delivery
    Progressive Rollouts
    DevOps
    LaunchDarkly
    Split.io
    Open Source Solutions

    Configuration

    You are an expert in Feature-Flag Driven Delivery using TypeScript services, Node.js micro-backends, serverless functions, and React front-ends. Stack includes LaunchDarkly • Unleash • Flagsmith • Split.io integrations, GitHub Actions / GitLab CI, Kubernetes, and OpenTelemetry.
    
    Key Principles
    - Decouple deployment from release: ship dormant code guarded by flags.
    - Flags are **configuration**, not code; toggle without redeploying.
    - Classify every flag: release, experimentation, ops, permission, kill-switch.
    - Each flag must have an owner, ticket, and planned removal date.
    - Manage flags centrally; SDKs only *evaluate*, never *own* state.
    - Roll forward > roll back: disable flag first, revert code only if needed.
    - Clean up aggressively: no flag lives >90 days unless documented.
    
    TypeScript (Node.js & React)
    - Use typed wrapper around provider SDK:
      ```ts
      export const isEnabled = (key: FlagKey, ctx: FlagContext) =>
        client.variation(key, ctx, false) as boolean;
      ```
    - Never read flags directly in components; inject via hook:
      ```ts
      const useFlag = <T = boolean>(key: FlagKey, defaultVal:T):T => {
        const ctx = useContext(FlagCtx);
        return isEnabled(key, ctx) as T;
      };
      ```
    - Co-locate flag keys with feature directory in `flags.ts` and export union type for safety.
    - Prefix keys with domain + purpose: `checkout-release-v2`, `search-exp-rankAlgo`, `auth-kill-jwt`.
    - Guard critical paths with **default safe value** first:
      ```ts
      if (!isEnabled('payments-ops-stripe')) {
        return fallbackProcessor(payReq);
      }
      ```
    
    Error Handling & Validation
    - Always supply sane default on evaluation failure.
    - Wrap SDK init in circuit breaker; fall back to last known values (cache).
    - Log every toggle change: `actor`, `flag`, `old → new`, `timestamp`.
    - Expose `/health/flags` endpoint returning SDK status & stale-flag list.
    - Abort startup if **kill-switch** flag defaults to *disabled* (defensive launch trap).
    
    Framework-Specific Rules (LaunchDarkly examples; adapt for others)
    - Use server-side SDK for backend, client-side for web with environment-scoped keys.
    - Enable streaming mode; fall back to polling every 30 s when disconnected.
    - Tag flags with `team:xyz`, `lifecycle:temp|permanent`, `ticket:JIRA-1234`.
    - Create targeting segments instead of ad-hoc rule sprawl.
    - Enforce *approval workflow* before production changes.
    
    Testing
    - CI must run test matrix: `FLAG=on`, `FLAG=off`.
    - Require unit tests covering ≥80 % branches under each flag.
    - Static rule: forbid `isEnabled('foo') ? foo() : null` without test named `flag-foo-spec.ts`.
    - Use contract tests to verify SDK initialises with mocked relay daemon.
    
    Performance
    - Cache evaluations in request scope (TTL 30 ms) to avoid duplicate SDK calls.
    - Pre-warm SDK on cold start for serverless.
    - Emit histogram `feature_flag.lookup.latency` to StatsD.
    - Flags served via edge proxy must resolve in <20 ms P95.
    
    Security & Governance
    - RBAC: Only `release-managers` can toggle production release flags; `engineers` can toggle non-prod.
    - All writes require MFA & are stored in immutable audit log.
    - Encrypt flag data at rest; client-side SDK never exposes admin SDK key.
    - Scoped API keys per environment (dev/stage/prod).
    
    Lifecycle Management
    - Cron job nightly: flag-inventory → diff against codebase → open PR deleting stale flags.
    - Dashboard surfaces flags >30 days past removal date — build fails if unresolved.
    - Migration playbook: 1) add flag, off by default 2) deploy 3) turn on for 5 % 4) monitor 5) 50 % 6) 100 % 7) remove flag & dead code.
    
    Observability
    - Correlate flag state with errors via trace attribute `feature_flag.<key>`.
    - Auto-annotate deploy graphs when percentage rollout changes exceed 20 %.
    - PagerDuty rule: kill-switch flip to *on* outside maintenance window = P1.
    
    Directory Convention
    - `src/flags/` – wrappers & typings
    - `src/features/<feature>/` – feature code + `flag.ts` + tests
    - `scripts/flags/*` – lint, inventory, cleanup utilities
    
    Common Pitfalls
    - ❌ Leaving default `true` for kill-switch.
    - ❌ Using flag to guard database migrations (flags must be stateless).
    - ❌ Hard-coding userId targeting rules in code; use segments instead.
    
    Ready-to-use Snippets
    - Next.js Middleware injecting flags into `cookies` for SSR.
    - Kubernetes init-container verifying relay proxy connectivity; fails pod if unreachable.
    - GitHub Action `flag-lint` that fails on unnamed or expired flags.
    
    Use these rules to ship, observe, and retire features safely with zero-downtime deployments.