Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
bagelhole avatar

Feature Flags

  • 80 installs
  • 44 repo stars
  • Updated May 22, 2026
  • bagelhole/devops-security-agent-skills

feature-flags is a Claude skill that implements feature flags for progressive rollout using LaunchDarkly, Unleash, or custom database-backed solutions.

About

feature-flags implements feature flags for progressive feature rollout using LaunchDarkly, Unleash, or custom solutions. A developer uses it to control feature visibility, run A/B tests, and enable trunk-based development with kill switches. It ships code that gates features behind flags with targeting and percentage rollout rules.

  • SDK setup for LaunchDarkly and Unleash (Node.js and React)
  • Targeting rules and percentage rollout strategies
  • Database-backed custom feature flag implementation

Feature Flags by the numbers

  • 80 all-time installs (skills.sh)
  • Ranked #125 of 248 Release Management skills by installs in the Skillselion catalog
  • Data as of Jul 28, 2026 (Skillselion catalog sync)
At a glance

feature-flags capabilities & compatibility

Skill is free; LaunchDarkly needs an SDK key, self-hosted Unleash and the custom option are free.

Capabilities
feature flagging · ab testing · gradual rollout
Works with
postgres
Use cases
testing · devops
Runs
Runs locally
Pricing
Free
From the docs

What feature-flags says it does

Implement feature flags for progressive feature rollout using LaunchDarkly, Unleash, or custom solutions.
SKILL.md
Control feature releases and enable progressive rollout with feature flag systems.
SKILL.md
npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill feature-flags

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs80
repo stars44
Last updatedMay 22, 2026
Repositorybagelhole/devops-security-agent-skills

What it does

Gate new features behind flags to do gradual rollouts, A/B tests, and instant kill switches in production.

Who is it for?

Teams doing gradual rollouts, trunk-based development, or A/B experiments behind toggles.

Skip if: Simple projects that ship all features to everyone at once with no rollout control.

When should I use this skill?

You are implementing gradual rollouts, feature toggles, kill switches, or experimentation platforms.

What you get

Features gated behind flags with targeting rules, percentage rollouts, and kill switches.

  • SDK integration code
  • targeting and rollout rules
  • custom flag service

By the numbers

  • 5 feature flag types (Release, Experiment, Ops, Permission, Kill Switch)
  • 3 provider paths (LaunchDarkly, Unleash, custom)

Files

SKILL.mdMarkdownGitHub ↗

Feature Flags

Control feature releases and enable progressive rollout with feature flag systems.

When to Use This Skill

Use this skill when:

  • Implementing gradual feature rollouts
  • Enabling trunk-based development
  • Running A/B tests and experiments
  • Managing feature lifecycles
  • Implementing kill switches for production

Prerequisites

  • Application code access
  • Feature flag service or self-hosted solution
  • Basic understanding of deployment patterns

Feature Flag Types

TypePurposeExample
ReleaseControl feature visibilityNew checkout flow
ExperimentA/B testingButton color test
OpsRuntime configurationRate limiting
PermissionUser access controlPremium features
Kill SwitchEmergency disableThird-party integration

LaunchDarkly

SDK Setup (Node.js)

const LaunchDarkly = require('launchdarkly-node-server-sdk');

const client = LaunchDarkly.init(process.env.LAUNCHDARKLY_SDK_KEY);

await client.waitForInitialization();

// Evaluate flag
const user = {
  key: 'user-123',
  email: 'user@example.com',
  custom: {
    plan: 'premium',
    company: 'acme'
  }
};

const showNewFeature = await client.variation('new-checkout', user, false);

if (showNewFeature) {
  // New feature code
} else {
  // Existing code
}

React SDK

import { withLDProvider, useFlags, useLDClient } from 'launchdarkly-react-client-sdk';

// Provider setup
export default withLDProvider({
  clientSideID: 'your-client-side-id',
  user: {
    key: 'user-123',
    email: 'user@example.com'
  }
})(App);

// Using flags in component
function FeatureComponent() {
  const { newCheckout, experimentVariant } = useFlags();
  const ldClient = useLDClient();

  // Track events
  const handleClick = () => {
    ldClient.track('checkout-started');
  };

  if (newCheckout) {
    return <NewCheckout onClick={handleClick} />;
  }
  return <OldCheckout onClick={handleClick} />;
}

Targeting Rules

# LaunchDarkly targeting configuration
flag: new-checkout
targeting:
  # Individual users
  targets:
    - variation: true
      values: ['user-123', 'user-456']
  
  # Rules
  rules:
    # Beta users
    - variation: true
      clauses:
        - attribute: email
          op: endsWith
          values: ['@company.com']
    
    # Premium plan
    - variation: true
      clauses:
        - attribute: plan
          op: in
          values: ['premium', 'enterprise']
    
    # Percentage rollout
    - variation: true
      rollout:
        variations:
          - variation: true
            weight: 20000  # 20%
          - variation: false
            weight: 80000  # 80%
  
  # Default
  fallthrough:
    variation: false

Unleash

Server Setup

# docker-compose.yml
version: '3.8'

services:
  unleash:
    image: unleashorg/unleash-server:latest
    ports:
      - "4242:4242"
    environment:
      - DATABASE_URL=postgres://postgres:password@db/unleash
      - DATABASE_SSL=false
    depends_on:
      - db

  db:
    image: postgres:15
    environment:
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=unleash
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  postgres-data:

SDK Setup (Node.js)

const { initialize } = require('unleash-client');

const unleash = initialize({
  url: 'http://localhost:4242/api',
  appName: 'my-app',
  customHeaders: {
    Authorization: 'your-api-token'
  }
});

unleash.on('ready', () => {
  // Check feature
  const isEnabled = unleash.isEnabled('new-checkout');
  
  // With context
  const context = {
    userId: 'user-123',
    properties: {
      plan: 'premium'
    }
  };
  
  const isEnabledForUser = unleash.isEnabled('new-checkout', context);
  
  // Get variant
  const variant = unleash.getVariant('experiment-flag', context);
  console.log(variant.name); // 'control' or 'treatment'
});

Activation Strategies

# Standard strategies
strategies:
  - name: default
    # On/off for everyone
    
  - name: userWithId
    parameters:
      userIds: 'user-1,user-2,user-3'
    
  - name: gradualRolloutUserId
    parameters:
      percentage: 25
      groupId: 'new-feature'
    
  - name: gradualRolloutRandom
    parameters:
      percentage: 50
    
  - name: flexibleRollout
    parameters:
      rollout: 30
      stickiness: userId
      groupId: 'checkout-exp'

Custom Implementation

Database-Backed Flags

# models.py
from django.db import models

class FeatureFlag(models.Model):
    name = models.CharField(max_length=100, unique=True)
    enabled = models.BooleanField(default=False)
    rollout_percentage = models.IntegerField(default=0)
    allowed_users = models.JSONField(default=list)
    rules = models.JSONField(default=dict)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

# service.py
import hashlib

class FeatureFlagService:
    def __init__(self):
        self._cache = {}
    
    def is_enabled(self, flag_name, user_id=None, context=None):
        flag = self._get_flag(flag_name)
        
        if not flag or not flag.enabled:
            return False
        
        # Check user allowlist
        if user_id and user_id in flag.allowed_users:
            return True
        
        # Check rules
        if context and self._evaluate_rules(flag.rules, context):
            return True
        
        # Check percentage rollout
        if flag.rollout_percentage > 0 and user_id:
            return self._is_in_rollout(flag_name, user_id, flag.rollout_percentage)
        
        return flag.rollout_percentage == 100
    
    def _is_in_rollout(self, flag_name, user_id, percentage):
        hash_input = f"{flag_name}:{user_id}"
        hash_value = int(hashlib.md5(hash_input.encode()).hexdigest(), 16)
        return (hash_value % 100) < percentage
    
    def _evaluate_rules(self, rules, context):
        for rule in rules.get('rules', []):
            if self._evaluate_rule(rule, context):
                return True
        return False

Redis-Backed Flags

import redis
import json

class RedisFeatureFlags:
    def __init__(self, redis_url):
        self.redis = redis.from_url(redis_url)
        self.prefix = 'feature_flag:'
    
    def set_flag(self, name, config):
        key = f"{self.prefix}{name}"
        self.redis.set(key, json.dumps(config))
    
    def is_enabled(self, name, user_id=None):
        key = f"{self.prefix}{name}"
        data = self.redis.get(key)
        
        if not data:
            return False
        
        config = json.loads(data)
        
        if not config.get('enabled', False):
            return False
        
        # User allowlist
        if user_id in config.get('users', []):
            return True
        
        # Percentage rollout
        percentage = config.get('percentage', 0)
        if percentage == 100:
            return True
        
        if percentage > 0 and user_id:
            return self._hash_user(name, user_id) < percentage
        
        return False
    
    def _hash_user(self, flag, user_id):
        import hashlib
        hash_input = f"{flag}:{user_id}"
        return int(hashlib.sha256(hash_input.encode()).hexdigest(), 16) % 100

Testing with Feature Flags

Unit Testing

// Jest mocking
jest.mock('launchdarkly-node-server-sdk', () => ({
  init: jest.fn(() => ({
    waitForInitialization: jest.fn().mockResolvedValue(undefined),
    variation: jest.fn()
  }))
}));

describe('Checkout', () => {
  it('shows new checkout when flag enabled', async () => {
    const ldClient = require('launchdarkly-node-server-sdk').init();
    ldClient.variation.mockResolvedValue(true);
    
    const result = await renderCheckout(user);
    expect(result).toContain('NewCheckout');
  });
  
  it('shows old checkout when flag disabled', async () => {
    const ldClient = require('launchdarkly-node-server-sdk').init();
    ldClient.variation.mockResolvedValue(false);
    
    const result = await renderCheckout(user);
    expect(result).toContain('OldCheckout');
  });
});

Integration Testing

# pytest fixtures
import pytest

@pytest.fixture
def feature_flags():
    """Provide controllable feature flags for testing."""
    flags = {}
    
    class TestFlags:
        def set(self, name, value):
            flags[name] = value
        
        def is_enabled(self, name, **kwargs):
            return flags.get(name, False)
    
    return TestFlags()

def test_new_checkout(feature_flags):
    feature_flags.set('new-checkout', True)
    
    response = client.get('/checkout')
    assert 'new-checkout-form' in response.content

Monitoring and Analytics

Flag Usage Tracking

// Track flag evaluations
const flagMetrics = {
  evaluations: new Map(),
  
  track(flagName, variation, user) {
    const key = `${flagName}:${variation}`;
    const count = this.evaluations.get(key) || 0;
    this.evaluations.set(key, count + 1);
    
    // Send to analytics
    analytics.track('feature_flag_evaluated', {
      flag: flagName,
      variation: variation,
      userId: user.key
    });
  }
};

Stale Flag Detection

from datetime import datetime, timedelta

def detect_stale_flags():
    """Find flags that haven't been evaluated recently."""
    stale_threshold = timedelta(days=30)
    now = datetime.utcnow()
    
    stale_flags = []
    for flag in FeatureFlag.objects.all():
        if flag.last_evaluated:
            age = now - flag.last_evaluated
            if age > stale_threshold:
                stale_flags.append({
                    'name': flag.name,
                    'last_evaluated': flag.last_evaluated,
                    'age_days': age.days
                })
    
    return stale_flags

Common Issues

Issue: Inconsistent Flag Evaluation

Problem: Same user sees different variations Solution: Use consistent hashing, check caching strategy

Issue: Flag Debt Accumulation

Problem: Too many old flags in codebase Solution: Implement flag lifecycle, regular cleanup sprints

Issue: Performance Impact

Problem: Flag evaluation slowing requests Solution: Use local caching, batch evaluations

Best Practices

  • Use consistent naming conventions
  • Document flag purpose and owner
  • Set expiration dates for temporary flags
  • Implement flag lifecycle management
  • Use gradual rollouts (not 0→100)
  • Monitor flag evaluation metrics
  • Clean up old flags regularly
  • Test both variations in CI

Related Skills

  • blue-green-deploy - Deployment strategies
  • git-workflow - Trunk-based development
  • alerting-oncall - Monitoring rollouts

Related skills

FAQ

Which feature flag providers does this cover?

LaunchDarkly, Unleash, and a custom database-backed implementation.

What flag types are supported?

Release, Experiment, Ops, Permission, and Kill Switch flags.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.