Skip to Content
Best Practices

Best Practices

Guidelines for using feature flags effectively and avoiding common pitfalls.

Flag lifecycle

Follow a clear lifecycle for each flag: CreateRoll outMonitorClean up / archive.

  1. Create — Define the flag with a clear key and type (boolean or JSON)
  2. Roll out — Start with internal users, then beta, then gradual percentage ramp (see Release workflow)
  3. Monitor — Use the Overview tab to track exposure and behavior
  4. Clean up — Remove or archive flags once the feature is fully rolled out and stable

Leaving old flags in place causes confusion and drift. Archive or delete them when no longer needed.

Test before ramp

Use the SDK Toolbar locally to validate variants before changing production targeting rules. Override flag values in development, test both enabled and disabled states, then configure rollout rules in the dashboard once confident.

Remote config

For JSON flags, do not store secrets (API keys, passwords) in remote config — manage those with proper secret management tools. Use stable, descriptive keys for config values so targeting rules stay maintainable.

Feature Flag Naming

Use Descriptive Names

// ✅ Good naming 'new-checkout-flow' 'beta-features' 'admin-panel-v2' 'pricing-page-redesign' // ❌ Avoid 'flag1' 'new-feature' 'test-flag' 'feature-123'

Use Consistent Patterns

// ✅ Group related flags with prefixes 'checkout.new-flow' 'checkout.express-payment' 'checkout.guest-checkout' // ✅ Use prefixes for different types 'landing.new-hero-section' 'config.max-retries' // Configuration 'beta.new-features' // Beta features // ✅ Use versions for flags that are updated frequently 'checkout.new-flow.v1' 'checkout.new-flow.v2'

Avoid Environment-Specific Names

// ❌ Don't include environment in flag names 'beta-feature-dev' 'beta-feature-prod' // ✅ Use environment-agnostic names 'beta-feature'

Performance

Batch evaluation: Evaluate multiple flags in one request when possible.

const flags = await client.getFeatures({ features: ['feature-a', 'feature-b', 'feature-c'], context: user, })

Security

Use Client Keys for frontend apps (safe to expose publicly).
Use Server Keys for backend services (keep secret).

Client keys can only read flags. Server keys have full access.

Common Anti-Patterns

Don’t Use Flags for Everything

// ❌ Don't use flags for everything if (isFeatureEnabled('show-button')) { return <Button /> } // ✅ Use flags for meaningful features if (isFeatureEnabled('new-checkout-flow')) { return <NewCheckout /> } else { return <OldCheckout /> }

Don’t Nest Flags Deeply

// ❌ Don't nest flags deeply if (isFeatureEnabled('feature-a')) { if (isFeatureEnabled('feature-b')) { if (isFeatureEnabled('feature-c')) { // Complex nested logic } } } // ✅ Use a single flag for complex features if (isFeatureEnabled('advanced-feature-set')) { // Handle all advanced features together }

Clean up old flags

As part of the flag lifecycle, archive or delete flags once features are fully rolled out and stable.

Last updated on