Skip to main content

Plan, create, roll out, and retire feature flags without accumulating tech debt

Flag Lifecycle & Best Practices

Feature flags are powerful, but without discipline they become tech debt. This guide covers the full lifecycle of a flag — from planning through cleanup — and the conventions that keep your flag inventory manageable.

Lifecycle Stages

Every flag should move through these stages:

Plan → Create → Test → Roll Out → Monitor → Clean Up

1. Plan

Before creating a flag, decide:

  • What decision does this flag control? A single flag should control a single feature or behavior change.
  • What type of flag is it? (See Flag Type Selection below.)
  • Who should see the feature? Define your targeting strategy upfront.
  • What's the rollout plan? Will you do a progressive rollout or a hard switch?
  • When will you remove it? Set a target cleanup date. Flags without an exit plan become permanent.

2. Create

Create the flag in the development environment first:

curl -X POST /api/flags \
  -H "Authorization: Bearer flg_your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "checkout-v2",
    "name": "Checkout V2",
    "description": "New streamlined checkout flow with fewer steps",
    "type": "boolean",
    "enabled": false,
    "defaultValue": false,
    "serviceId": "web-app",
    "environment": "development",
    "tags": ["checkout", "q1-2026"]
  }'

3. Test

Enable the flag in development and verify both paths (flag on and flag off). Use overrides to force specific values for specific test users.

4. Roll Out

Promote the flag through environments:

  1. Development — Full rollout, verify functionality
  2. Staging — Full rollout, run integration tests
  3. Production — Progressive rollout (5% → 25% → 50% → 100%)

Use progressive rollouts for production-critical features.

5. Monitor

While the flag is rolling out:

6. Clean Up

Once the feature is fully rolled out and stable:

  1. Remove the flag checks from your code (always ship the "on" path)
  2. Delete the flag from Flaggr
  3. Remove any related targeting rules, overrides, and cohorts
Warning

Flag tech debt is the #1 complaint from teams adopting feature flags. Set a cleanup date when you create the flag. Use tags like q1-2026 to track cleanup targets. Review stale flags monthly.

Naming Conventions

Flag Keys

Flag keys must match the pattern ^[a-zA-Z][a-zA-Z0-9_-]*$:

  • Start with a letter
  • Contain only letters, numbers, hyphens, and underscores
  • Use kebab-case by convention
PatternExampleWhen to Use
feature-namecheckout-v2Simple feature flag
feature-name-variantpricing-page-layoutA/B test or multi-variant
ops-featureops-rate-limit-overrideOperational control
exp-hypothesisexp-shorter-signupExperiment

Flag Names

Use human-readable names that non-engineers can understand:

  • Good: "Checkout V2", "Dark Mode", "Holiday Banner"
  • Bad: "feature_flag_123", "test", "new thing"

Tags

Use tags to categorize and track flags:

Tag PatternPurpose
q1-2026Cleanup target quarter
checkoutFeature area
experimentFlag is part of an experiment
opsOperational control (not a feature rollout)
permanentIntentionally long-lived (entitlements, kill switches)

Flag Type Selection

Choose the right type for your use case:

Boolean — On/Off Decisions

The most common type. Use for feature gates, kill switches, and simple rollouts.

const showNewCheckout = await client.getBooleanValue("checkout-v2", false);

String — Configuration and Variants

Use for A/B tests with named variants, theme selection, or configuration values.

const theme = await client.getStringValue("app-theme", "light");
// Returns: "light", "dark", or "system"

Number — Numeric Controls

Use for rate limits, thresholds, percentages, and numeric parameters.

const maxRetries = await client.getNumberValue("max-retries", 3);

Object — Complex Configuration

Use for structured configuration that doesn't fit a single value. Keep objects small and well-typed.

const bannerConfig = await client.getObjectValue("promo-banner", {
  text: "",
  color: "blue",
  dismissible: true,
});
Info

Default to boolean. Most flags are simple on/off decisions. Only use string, number, or object when boolean doesn't capture what you need.

Organizing Flags by Service

Group flags by the application that evaluates them:

ServiceFlags
web-appUI features, client-side experiments
apiBackend behavior, rate limits, algorithm switches
mobile-iosiOS-specific features
mobile-androidAndroid-specific features
workerBackground job controls

Don't create a single "all flags" service. Flags in a service share targeting context and evaluation scope.

Environment Promotion Workflow

A disciplined promotion workflow prevents accidental production changes:

development → staging → production
    ↓             ↓           ↓
  Create      Validate    Progressive
  & test      with CI     rollout

Use the export/import API to promote flag configurations between environments:

# Export from staging
curl "/api/flags/export?projectId=proj-123&environment=staging" \
  -H "Authorization: Bearer flg_token" \
  -o staging-flags.json
 
# Import to production (dry run first)
curl -X POST /api/flags/import \
  -H "Authorization: Bearer flg_prod_token" \
  -H "Content-Type: application/json" \
  -d '{
    "flags": [...],
    "conflictResolution": "skip",
    "dryRun": true
  }'

Tech Debt Management

Flag Inventory Review

Schedule a monthly review of your flag inventory:

  1. List all flags sorted by creation date
  2. Identify stale flags — flags older than their cleanup target
  3. Check for fully-rolled-out flags — 100% rollout for 2+ weeks means it's time to remove the code wrapper
  4. Archive completed experiments — Document results, then delete the flag

Warning Signs

SignalAction
Flag created 3+ months ago, still at 100% rolloutRemove the flag and code wrapper
Flag with no evaluations in 30 daysVerify it's still referenced in code; delete if not
Flag with 50+ targeting rulesSimplify with cohorts or split into multiple flags
Flag with enabled: false for 2+ monthsEither finish the feature or delete the flag

Permanent Flags

Some flags are intentionally long-lived. Tag these as permanent and document why:

  • Kill switches — Emergency shutoff for critical features
  • Entitlements — Gate features by user plan (free vs pro vs enterprise)
  • Operational controls — Rate limits, cache TTLs, algorithm parameters
  • Compliance — Region-specific behavior (GDPR, data residency)