# Feature Flags

> When to activate: feature flags, feature toggles, gradual rollout, kill switch, LaunchDarkly, Unleash, A/B testing infrastructure, flag governance

- Skill: `mattakushi432/feature-flags` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mattakushi432/feature-flags`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mattakushi432/feature-flags/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Mattakushi432 (https://skillmd.com/u/mattakushi432)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mattakushi432/feature-flags

---


# Feature Flags

## Flag Types

| Type | Purpose | Lifespan | Example |
|------|---------|----------|---------|
| **Release flag** | Hide incomplete features | Short (days–weeks) | `new_checkout_flow` |
| **Experiment flag** | A/B test variants | Short (experiment duration) | `pricing_page_variant_b` |
| **Ops flag** | Runtime behavior control | Long (permanent) | `enable_rate_limiting` |
| **Permission flag** | Entitlement by user/plan | Long (business-driven) | `feature_advanced_analytics` |

## Gradual Rollout Strategy

```
1%  → Internal users / employees only
5%  → Alpha users / trusted beta
25% → Broader beta cohort
50% → Half of traffic (monitor metrics)
100% → Full rollout → schedule flag cleanup
```

### Rollout Criteria at Each Gate
- Error rate < baseline + 0.5%
- Latency p99 within 10% of control
- No critical bug reports
- Key business metrics not degrading

## Flag Naming Conventions

```
Format: <scope>_<feature>_<variant?>

Good:
  checkout_v2_enabled
  pricing_annual_discount_variant_b
  api_rate_limit_enabled

Bad:
  flag1
  newFeature
  CHECKOUT_V2 (avoid ALL_CAPS)
```

### Naming Rules
- Lowercase with underscores
- Start with scope/domain prefix
- Boolean flags: use `_enabled` suffix
- Experiment flags: use `_variant_[a|b|c]` suffix
- Avoid negatives: `disable_X` creates double-negative confusion

## Kill Switch Design

A kill switch is an ops flag that defaults to ON and disables a feature when flipped OFF.

```python
# Pattern: default ON, flip OFF to disable
if feature_flags.is_enabled("payment_processing_enabled", default=True):
    process_payment(order)
else:
    return ServiceUnavailableError("Payment processing temporarily unavailable")
```

### Kill Switch Checklist
- [ ] Default value is `True` (feature active)
- [ ] Graceful degradation path defined
- [ ] User-facing error message ready
- [ ] Runbook documented: when to flip, who can flip, how to re-enable
- [ ] Alert wired to flag state change

## Flag Lifecycle Management

```
CREATED → ACTIVE → RAMPING → FULLY_ROLLED_OUT → DEPRECATED → REMOVED
```

### Lifecycle Gates
| Stage | Action | Owner |
|-------|--------|-------|
| Created | Add to registry, set default, document intent | Engineer |
| Active | Gradual rollout begins, metrics monitored | PM + Engineer |
| Fully rolled out | 100% traffic, stable for ≥ 2 weeks | PM |
| Deprecated | Removal ticket created, countdown timer set | Engineer |
| Removed | Code deleted, flag removed from system | Engineer |

### Stale Flag Detection
Flag is stale when:
- Age > 90 days with no rollout changes
- 100% rollout for > 30 days (release flags)
- Experiment concluded but flag not removed

## Governance Checklist

Before creating a flag:
- [ ] Flag type selected (release/experiment/ops/permission)
- [ ] Owner assigned (PM + Engineer)
- [ ] Removal date or criteria defined
- [ ] Fallback behavior documented
- [ ] Metrics to monitor during rollout identified

Before full rollout:
- [ ] Rollout gates passed (error rate, latency, metrics)
- [ ] Removal ticket created in backlog
- [ ] Cleanup PR planned for next sprint

## LaunchDarkly vs Unleash vs Homegrown

| | LaunchDarkly | Unleash | Homegrown |
|-|-------------|---------|-----------|
| **Setup time** | Hours | Days | Weeks–months |
| **Cost** | $$$$ | Free (OSS) / $$ (cloud) | Engineering time |
| **Targeting** | Advanced (segments, rules) | Good | You build it |
| **Analytics** | Built-in | Limited | You build it |
| **Audit log** | Yes | Yes | You build it |
| **Best for** | Scale + compliance needs | Cost-conscious / OSS preference | Simple use cases only |

### Decision Matrix
- < 5 flags, simple on/off → Homegrown (env vars)
- Growth stage, experiment-heavy → Unleash OSS
- Enterprise, compliance, advanced targeting → LaunchDarkly

## Technical Debt from Flags

### Flag Debt Accumulates When
- Experiments conclude but flags remain in code
- 100%-rolled-out flags are not cleaned up
- Flags reference deleted features
- Flag logic creates complex conditionals

### Cleanup Process
1. Audit flags monthly (automated report from registry)
2. Assign cleanup tickets for all deprecated flags
3. Remove flag evaluation + dead code branch in same PR
4. Update tests — remove flag-conditional test variants
5. Verify no references remain (`grep -r "flag_name" .`)

### Cost of Flag Debt
- Each live flag adds a conditional branch in production code
- 50+ stale flags = significant cognitive overhead
- Nested flag conditionals are extremely hard to reason about
- Rule: delete the losing variant's code; don't just remove the flag check

