smaple.tr
feature flags

Feature Flags and Progressive Delivery: Deployment Risk Management Guide [2026]

Mehmet Kurtipek
July 11, 2026
11 min read
feature flags
progressive delivery
canary deployment
A/B testing
LaunchDarkly
Unleash
DevOps

Deployment and release used to mean the same thing. You deployed code, and users saw it — simultaneously, for better or worse. Feature flags decouple those two events. Code can be deployed to production for weeks before any user sees it. A feature can be enabled for 1% of users, then 10%, then 50%, with automatic rollback if error rates spike. The same infrastructure enables A/B experiments that run without additional deployments.

This guide covers feature flag fundamentals, progressive delivery strategies, tool selection (LaunchDarkly, Unleash, Flagsmith), SDK integration patterns, A/B testing with flags, and the lifecycle management practices that prevent flags from becoming technical debt. By the end, you will have an architecture for risk-controlled software releases.

Feature Flags: Separating Deployment from Release

A feature flag is a conditional check in code that controls whether a feature is visible to users. The simplest form:

if (featureFlags.isEnabled('new-checkout-flow', { userId: user.id })) {
  return newCheckoutFlow(user);
} else {
  return legacyCheckoutFlow(user);
}

The flag is evaluated at runtime, not deploy time. Changing whether a feature is enabled requires updating a configuration value, not deploying new code. This is the mechanism that separates deployment from release.

Why this matters operationally: A deployment is a technical operation — it can be automated and run at any time. A release is a business decision — it should happen when marketing is ready, when the feature is validated, and with appropriate risk controls. Mixing them forces business timing onto the deployment schedule, which increases deployment risk and reduces deployment frequency.

Feature flags enable:

  • Deploying unfinished features hidden behind a flag (trunk-based development)
  • Releasing to subsets of users to gather feedback before full rollout
  • Instant rollback without deployment (toggle the flag, not the code)
  • A/B experiments without separate deployments
  • Operational kill switches for emergency service degradation

Feature Flag Types

Different flag types serve different operational purposes. Treating all flags the same creates lifecycle management problems.

Release Flags

Release flags control whether a newly developed feature is visible to users. They are inherently temporary: once the feature is fully rolled out and validated, the flag should be removed and the conditional code cleaned up.

Release flags that are not removed accumulate as technical debt. The conditional code path must be maintained, tested, and reasoned about indefinitely. A flag left in place for six months after full rollout is a maintenance liability.

Target lifecycle: creation → development → progressive rollout → 100% enabled → code cleanup. Maximum duration: four to six weeks from creation.

Experiment Flags

Experiment flags drive A/B and multivariate tests. They assign users to variants consistently (the same user always sees the same variant), track variant exposure, and enable statistical analysis of behavior differences.

Experiment flags have a natural end state: the experiment concludes, a variant wins, and the flag is removed along with the losing variant's code. Their lifecycle is bounded by the experiment duration.

Operational (Kill Switch) Flags

Kill switch flags provide real-time control over system behavior for operational purposes. When an external payment service is degraded, enabling the payment-service-degraded flag switches to a graceful fallback. When a third-party API is rate-limiting, an ops flag can disable the feature that drives those calls.

Kill switches are long-lived. They exist for as long as the system behavior they control is relevant. They do not represent technical debt — they represent intentional operational controls.

Permission Flags

Permission flags control feature access based on user attributes: subscription tier, geographic region, enterprise account, or beta program membership. They are also long-lived.

Flag type Typical lifetime Change frequency Technical debt risk
Release Days to weeks Low High if not cleaned up
Experiment Weeks to months Medium Medium
Operational Permanent Rare Low
Permission Permanent Rare Low

Progressive Delivery Strategies

Progressive delivery means releasing to increasingly larger user segments, monitoring at each stage, and proceeding only when metrics are healthy.

Canary Deployment

Canary deployment routes a small percentage of users to the new version. A typical progression:

canary:
  steps:
    - percentage: 1
      duration: 10m
      success_criteria:
        - error_rate < 0.5%
        - p99_latency < 500ms
    - percentage: 5
      duration: 30m
    - percentage: 25
      duration: 1h
    - percentage: 50
      duration: 2h
    - percentage: 100

If error rate or latency exceeds the threshold at any stage, the rollout stops and optionally reverts. The damage is contained: 1% of users experienced the problem, not 100%.

Canary deployment requires observability infrastructure: you need metrics per user segment to know whether the 1% on the new version is behaving differently from the 99% on the old version.

Blue-Green with Feature Flags

Blue-green deployment combined with feature flags provides multiple risk reduction layers. The application is deployed to a parallel environment (green) with all new features disabled. Traffic switches to green (zero-downtime), then features are progressively enabled via flags.

This separates deployment risk (is the new code serving traffic correctly?) from feature risk (does the new feature behave correctly at scale?).

Ring-Based Deployment

Microsoft popularized ring-based deployment for large user bases. Users are segmented into concentric rings:

Ring User segment Exposure Monitoring period
Ring 0 Internal developers 0.1% 1 day
Ring 1 Internal employees 1% 2 days
Ring 2 Beta users 10% 3 days
Ring 3 Early adopters 50% 1 week
Ring 4 All users 100% —

The ring model works at enterprise scale where statistical significance requires large user counts at each stage, and where different user populations have different risk tolerances.

Feature Flag Tool Selection

LaunchDarkly

LaunchDarkly is the category leader for enterprise feature management. Its strengths are the SDK ecosystem (30+ languages and frameworks), real-time flag evaluation with sub-millisecond latency, sophisticated targeting rules (user attributes, percentage rollout, geolocation, custom properties), and first-class A/B experiment support.

LaunchDarkly's pricing is usage-based and becomes significant at large scale. For teams managing hundreds of flags across dozens of services, the management console and audit history are genuine productivity multipliers.

Use LaunchDarkly when: your organization manages a high volume of flags, you need sophisticated targeting rules, or you need first-class A/B experiment support with statistical significance calculations.

Unleash

Unleash is the leading open-source feature flag platform. It supports self-hosted deployment (full data ownership) and a cloud-hosted option. The activation strategy ecosystem covers gradual rollout, user ID targeting, IP targeting, and custom strategies.

The self-hosted model means no per-seat or per-request pricing. For cost-sensitive organizations or those with strict data residency requirements, Unleash's open-source model is compelling.

Unleash's SDKs cover the major languages and frameworks, though the ecosystem is smaller than LaunchDarkly's.

Flagsmith

Flagsmith combines feature flags with remote configuration (the ability to push non-boolean values — strings, numbers, JSON — to running applications without a deployment). This makes it useful for scenarios like adjusting rate limits, toggling between API endpoints, or changing UI copy without deployment.

Flagsmith is open source with a cloud-managed option, similar to Unleash.

OpenFeature

OpenFeature is a CNCF project that defines a standard API for feature flag evaluation. Rather than a flag management system, it is an abstraction layer: applications code against the OpenFeature API, and the backend (LaunchDarkly, Unleash, Flagsmith, or a custom system) is swapped without application code changes.

For organizations that want to avoid vendor lock-in while still using managed services, OpenFeature provides the abstraction.

Feature LaunchDarkly Unleash Flagsmith OpenFeature
License Commercial Open source Open source Open standard
Self-hosted No Yes Yes N/A (protocol)
SDK count 30+ 15+ 15+ 10+
A/B testing Yes Limited Yes Provider-dependent
Real-time targeting Yes Yes Yes Provider-dependent
Pricing High Free/Enterprise Free/Enterprise Free

SDK Integration Patterns

Server-Side Integration

Server-side evaluation is the standard pattern for backend services. The SDK initializes with a connection to the flag management service, caches the current flag values locally, and evaluates flags in microseconds using the local cache.

from unleash_client import UnleashClient

client = UnleashClient(
    url="https://unleash.example.com/api",
    app_name="payment-service",
    custom_headers={"Authorization": "Bearer API_TOKEN"}
)
client.initialize_client()

def process_payment(order, user):
    context = {
        "userId": user.id,
        "properties": {
            "plan": user.subscription_tier,
            "region": user.region
        }
    }

    if client.is_enabled("new-payment-processor", context):
        return process_with_new_processor(order)
    return process_with_legacy_processor(order)

The local cache means flag evaluation adds no network latency to request processing. The SDK polls for updates (typically every 15-30 seconds) or uses a streaming connection.

Client-Side Integration

Client-side flag evaluation has an additional security concern: flag configurations should not expose sensitive business logic or user targeting rules to the browser. The standard approach is server-side rendering of initial flag state, or a proxy that filters flag configurations before sending to clients.

// React with a feature flag hook
import { useFeatureFlag } from '@company/feature-flags';

function CheckoutPage() {
  const showExpressCheckout = useFeatureFlag('express-checkout', {
    defaultValue: false,
    context: { userId: currentUser.id }
  });

  return (
    <div>
      <CartSummary />
      {showExpressCheckout ? <ExpressCheckoutFlow /> : <StandardCheckoutFlow />}
    </div>
  );
}

Default values are critical: flag evaluation must have a defined behavior when the flag management service is unreachable. Conservative defaults (feature disabled on network failure) are safer for operational flags; permissive defaults (feature enabled) may be appropriate for UX experiments.

A/B Testing with Feature Flags

Feature flag infrastructure provides the assignment mechanism for A/B experiments. Users are assigned to variants consistently (same user, same variant across sessions), exposure is tracked, and metrics are analyzed by variant.

Key requirements for valid A/B experiments:

Consistent assignment: Hash-based bucketing ensures the same user always receives the same variant. Session-based assignment (random on each page load) invalidates the experiment — you cannot measure behavioral differences when users see different variants in different sessions.

Single variable: Each experiment should test one change. Testing a new headline and a new button color simultaneously makes it impossible to determine which change caused the behavioral difference.

Predefined success metrics: Define what a winning variant looks like before the experiment starts. Analyzing data and then selecting metrics that happen to show the desired result is HARKing (Hypothesizing After Results are Known) and produces unreliable conclusions.

Statistical significance: Modern A/B testing platforms calculate statistical significance automatically. The common threshold is p < 0.05 (5% chance the result is random). Stopping an experiment early because results "look good" typically produces false positives.

Flag Lifecycle Management

The most common failure mode in feature flag systems is not technical — it is operational. Flags created but never removed accumulate over months and years. The codebase fills with conditional branches that nobody knows the purpose of. Testing requires maintaining all branch combinations. This is flag debt.

Preventing Flag Debt

Every flag should have a defined owner (team or individual), a type (release, experiment, operational, permission), and for release and experiment flags, an expiration date.

A flag configuration with lifecycle metadata:

const flagConfig = {
  key: 'new-payment-flow',
  type: 'release',
  owner: 'payments-team',
  jiraTicket: 'PAY-1234',
  createdAt: '2026-04-01',
  expiresAt: '2026-05-15', // 6 weeks maximum
  description: 'New payment checkout flow — Phase 2'
};

CI pipeline checks for expired flags should be implemented: builds warn (or fail) when a flag's expiration date has passed and it hasn't been removed.

Cleanup Automation

Automated flag cleanup notifications reduce the human coordination overhead:

  • Expired flag alerts sent to flag owners via Slack or email
  • Weekly flag inventory reports showing flags older than 30 days
  • PR checks that flag an expired feature flag reference in changed code

The goal is to make flag cleanup low-friction and visible, not dependent on engineers remembering to do it.

Feature Flags and CI/CD Integration

Feature flags are most powerful when integrated with the deployment pipeline:

# GitHub Actions progressive deployment
- name: Deploy to production
  run: ./deploy.sh

- name: Enable canary flag at 5%
  run: |
    curl -X PATCH "$FLAG_SERVICE_URL/api/flags/new-feature" \
      -H "Authorization: Bearer $FLAG_API_KEY" \
      -d '{"percentage": 5}'

- name: Monitor metrics for 10 minutes
  run: ./check-deployment-metrics.sh --duration=600 --threshold-error-rate=0.5

- name: Expand to 50% on success
  if: success()
  run: |
    curl -X PATCH "$FLAG_SERVICE_URL/api/flags/new-feature" \
      -d '{"percentage": 50}'

- name: Rollback on failure
  if: failure()
  run: |
    curl -X PATCH "$FLAG_SERVICE_URL/api/flags/new-feature" \
      -d '{"percentage": 0}'

This pattern — deploy code, enable flag for small percentage, verify metrics, expand — converts a high-risk big-bang deployment into a series of low-risk incremental steps, each with automatic rollback if metrics degrade.

Trunk-Based Development and Feature Flags

Trunk-based development means all engineers commit directly to the main branch (or merge feature branches within a day or two). Long-lived feature branches are not used. Instead, incomplete features live behind feature flags — they're deployed to production but invisible to users.

The advantages over long-lived branches:

  • No merge conflicts from weeks-old branches
  • Continuous integration actually integrates continuously
  • Main branch is always deployable
  • Code review focuses on small, reviewable commits rather than massive branch merges

Feature flags are the enabling mechanism for trunk-based development at scale. They allow independent teams to deploy their in-progress work simultaneously without coordination — each team controls when their feature is visible to users, independently of when it's deployed.

Related Articles

August 11, 2026

MLOps Guide: Taking Machine Learning Models to Production [2026]

87% of machine learning models built by data science teams never reach production. The models work — they pass cross-validation, they score well on holdout sets, they demonstrate genuine predictive value. The problem is not the modeling. The problem is everything that happens between a notebook experiment and a reliable, monitored, production system. MLOps is the discipline that closes that gap. This guide covers the full MLOps stack: maturity levels, tooling choices (MLflow, DVC, Kubeflow

Read More: MLOps Guide: Taking Machine Learning Models to Production [2026]
August 10, 2026

LLM Fine-Tuning Guide: Custom Model Training with LoRA and QLoRA [2026]

General-purpose LLMs are impressive. They can write code, summarize documents, answer questions, and translate between languages with reasonable accuracy. But "reasonable" is not good enough when your application requires consistent output format, domain-specific terminology, a particular tone, or behavior that the base model was never trained to exhibit. That gap is where fine-tuning matters. Fine-tuning updates a model's weights on your specific data, changing how the model behaves — not

Read More: LLM Fine-Tuning Guide: Custom Model Training with LoRA and QLoRA [2026]
August 9, 2026

Computer Vision Applications: Object Detection, OCR, and Industrial AI [2026]

Computer vision has moved well past the research phase. The models are trained, the frameworks are mature, the hardware is accessible, and the use cases are generating measurable returns. What was a specialized capability requiring deep expertise in 2018 is now deployable infrastructure — if you know which component to reach for and where the real complexity lives. This guide covers computer vision applications across industrial, medical, logistics, and document processing domains. It expl

Read More: Computer Vision Applications: Object Detection, OCR, and Industrial AI [2026]