Feature Flags at Scale: Implementation Patterns and Platform Comparison
A production-focused guide to implementing feature flags in distributed systems, comparing LaunchDarkly, Unleash, and AWS AppConfig with working examples for gradual rollouts, A/B testing, and managing technical debt.
Abstract
Feature flags enable deploying code to production while controlling feature visibility at runtime. This guide examines implementation patterns for feature flags at scale, comparing LaunchDarkly, Unleash, and AWS AppConfig platforms. I'll cover SDK integration, targeting rules, A/B testing integration, circuit breaker patterns, and the critical challenge of managing flag technical debt. Working TypeScript examples demonstrate gradual rollouts, kill switches, and lifecycle management strategies that prevent flags from becoming unmaintainable.
The Deployment Coordination Problem
Working with distributed systems reveals a persistent challenge: coordinating feature releases across teams creates bottlenecks. When multiple teams need to deploy features simultaneously, the typical approach involves careful scheduling, late-night deployments, and crossing fingers that nothing breaks.
The traditional solution; long-lived feature branches; brings its own problems. Branches diverge from main for weeks, merge conflicts multiply, and integration becomes increasingly painful. By the time the feature merges, it's been tested against code that no longer resembles production.
Feature flags offer a different approach: deploy code continuously to production, control feature visibility through runtime configuration. Instead of coordinating deployments, you coordinate flag rollouts. Instead of all-or-nothing releases, you enable features gradually for specific user segments.
Here's what we'll build toward: deploying incomplete features to production behind disabled flags, testing in production with real data, rolling out progressively from 1% to 100% of users, and having instant rollback capability when issues appear.
Understanding Feature Flag Types
Not all feature flags serve the same purpose. Understanding these types helps establish clear lifecycle expectations from the start.
Release Flags (Temporary)
Release flags control gradual rollout of new features. These flags have a clear lifecycle: created during development, enabled progressively during rollout, removed after reaching 100% adoption. Keeping these flags longer than necessary creates technical debt.
Experiment Flags (Temporary)
Experiment flags support A/B testing and multivariate experiments. Like release flags, these are temporary; they exist for the experiment duration and should be removed once the winning variation is implemented.
Ops Flags (Permanent)
Ops flags act as circuit breakers and kill switches. These are long-lived flags that provide operational control; the ability to disable features during incidents or high load conditions without deploying new code.
Permission Flags (Permanent)
Permission flags control feature access based on user attributes, subscription tiers, or entitlements. In SaaS applications, these flags manage which features are available to different customer segments.
Flag Lifecycle
Different flag types follow different lifecycle patterns:
Platform Comparison: LaunchDarkly vs Unleash vs AWS AppConfig
Choosing a feature flag platform involves evaluating trade-offs between cost, features, and operational complexity. Here's what I've learned from working with each platform.
Feature Comparison Matrix
LaunchDarkly: Enterprise Platform
LaunchDarkly provides the most mature feature flag platform with excellent UI/UX and comprehensive features.
Strengths:
- Advanced targeting rules with powerful segment capabilities
- Built-in experimentation platform
- Real-time flag updates via streaming connections
- Comprehensive audit logs and change history
- Strong enterprise features (RBAC, SSO, compliance)
Limitations:
- Expensive at scale (pricing combines per-seat and per-MAU costs)
- SaaS-only deployment (no self-hosted option)
- Vendor lock-in considerations
Cost Example (10 developers, 1M MAU, Pro tier):
- Note: LaunchDarkly pricing model has changed. Contact sales for current pricing.
- Historical reference: Pricing combined per-seat and per-MAU costs
Unleash: Open Source Alternative
Unleash offers open-source feature flags with the option to self-host or use their managed SaaS.
Strengths:
- Open source (Apache 2.0 license)
- Full control with self-hosting option
- Good SDK coverage across languages
- Active community
- Cost-effective for large user bases
Limitations:
- Less mature UI compared to LaunchDarkly
- Self-hosting adds operational overhead
- Limited experimentation features compared to LaunchDarkly
- Basic targeting capabilities
Cost Example (self-hosted):
- Infrastructure: ~$200/month (ECS/EC2, RDS)
- Operational overhead: ~$500/month (engineering time)
- Total: ~8,400/year)
AWS AppConfig: AWS-Native Solution
AWS AppConfig provides feature flags integrated with AWS services.
Strengths:
- Native AWS integration (Lambda, ECS, etc.)
- Pay-per-request pricing (cost-effective)
- FedRAMP certified
- No external service dependency
- Built-in validation and rollback
Limitations:
- Basic targeting capabilities
- Polling-based updates (not real-time)
- Limited to AWS SDK
- No native A/B testing support
- Basic dashboard compared to alternatives
Cost Example (1M requests/month):
- Requests: 1M × 0.20/month
- Configurations: 10 × 5/month
- Total: ~62/year)
Platform Selection Framework
LaunchDarkly SDK Integration
LaunchDarkly provides mature SDKs with local evaluation capabilities. Here's a production-ready integration pattern.
SDK Initialization
Type-Safe Flag Evaluation
Express Middleware Integration
Performance Note: Local evaluation reduces latency from 100-500ms (remote calls) to 1-5ms (local cache lookups).
Unleash SDK Integration
Unleash provides open-source SDKs with good performance characteristics.
SDK Setup
Context-Based Evaluation
Gradual Rollout Example
AWS AppConfig with Lambda Extension
AWS AppConfig integrates well with Lambda functions using the AppConfig Lambda Extension.
SDK Integration
Lambda Handler with Flags
Performance Improvement: Using the Lambda extension reduces cold start impact by caching configuration locally. The extension polls AppConfig every 45 seconds and serves requests from local cache.
Note: Add the AWS AppConfig Lambda Extension layer to your function:
The extension runs as a sidecar process and handles configuration fetching/caching automatically.
Targeting Rules and User Segmentation
Advanced targeting enables progressive rollouts and user-specific feature access.
Targeting Rule Implementation
Flag Evaluator
Progressive Rollout Configuration
Percentage Rollout Strategy: Use consistent hashing on user ID to ensure the same user always sees the same experience. This prevents users from seeing feature state flip between enabled/disabled on different requests.
A/B Testing Integration
Feature flags work well with analytics platforms for experimentation.
Analytics Integration
Experiment Implementation
Warning: A/B testing requires proper sample size calculation and statistical significance testing. Don't declare a winner after 100 users; wait for p-value < 0.05 and sufficient sample size. Consider using tools like Evan Miller's A/B test calculator to determine required sample size before starting experiments.
Kill Switches and Circuit Breakers
Operational flags enable quick response to incidents without deploying new code.
Circuit Breaker Implementation
Production Usage
Circuit Breaker States:
Flag Lifecycle Management
Technical debt from abandoned feature flags represents a significant challenge. Without active lifecycle management, flag count grows exponentially.
Lifecycle Tracking
Flag Removal Process
Cleanup Strategy:
- Identify flags that have reached 100% rollout (launched state)
- Verify flag always returns the same value
- Create pull request to remove flag code
- Deploy and monitor for issues
- Archive flag in platform
- Update documentation
Trunk-Based Development Integration
Feature flags enable trunk-based development by allowing incomplete features in the main branch.
Feature Toggle Pattern
Progressive Implementation
Benefits:
- No long-lived feature branches
- Continuous integration with main branch
- Smaller, more frequent merges
- Reduced merge conflicts
- Faster feedback loops
Testing Strategies
Testing feature-flagged code requires testing both enabled and disabled states.
Mock Flag Client
Test Both States
Warning: Don't test every combination of feature flags. With 10 flags, that's 1,024 test cases. Instead:
- Test critical features with flags both ON and OFF
- Use risk-based testing (test risky features more thoroughly)
- Mock flag client for predictable behavior
- Integration tests use dedicated test environment flags
Key Takeaways
Start with Clear Flag Types: Distinguish between release (temporary), experiment (temporary), ops (permanent), and permission (permanent) flags from the beginning. This establishes clear lifecycle expectations.
Choose Platform Based on Needs: AWS-native applications benefit from AppConfig's cost structure and integration. Complex targeting requirements favor LaunchDarkly's advanced capabilities. Budget-conscious teams with technical expertise should consider self-hosted Unleash.
Performance Requires Local Evaluation: SDK caching and local evaluation reduces latency from 100-500ms (remote calls) to 1-5ms (local lookups). This matters for high-traffic applications.
Flag Debt Accumulates Quickly: Without lifecycle management, flag count grows exponentially. Set expiration dates when creating flags, automate stale flag detection, and schedule regular cleanup.
Default to Safe Values: Feature flags should default to stable/legacy behavior. This ensures graceful degradation if the flag service becomes unavailable.
Test Both Code Paths: Every flag creates two execution paths. Test both in your CI/CD pipeline to catch issues before production.
Gradual Rollout Requires Monitoring: Progressive rollouts (1% → 5% → 25% → 50% → 100%) need comprehensive monitoring and clear rollback criteria. Define error rate thresholds before starting rollouts.
Kill Switches Reduce MTTR: Circuit breakers with automatic feature disabling can reduce mean time to recovery from hours to minutes during incidents.
Trunk-Based Development Works: Feature flags enable continuous integration without long-lived feature branches. Deploy incomplete features to production behind disabled flags.
A/B Testing Needs Statistical Rigor: Proper experiment design includes sample size calculation, statistical significance testing (p < 0.05), and avoiding common biases like the novelty effect.
Feature flags transform how teams deploy software; from coordinated big-bang releases to continuous, controlled rollouts. The key is treating flags as first-class citizens in your architecture with proper lifecycle management, rather than letting them accumulate into technical debt.