FeatureSignals
Guides

Progressive Delivery Patterns Every Team Should Know

Canary releases, ring-based deployments, percentage rollouts with consistent hashing, kill switches for emergency response, and A/B experiments with impression tracking — all implemented with feature flags. We show production patterns in Go and Node.js, how to structure your observability stack during rollouts, and what to monitor when you're pushing to 1% then 10% then 100% of users.

FE
FeatureSignals Engineering Team
·February 2026·9 min read

Beyond Basic Feature Toggles

Feature flags start simple: wrap new code in `if (flag) { ... }`. But that's just the beginning. The real power of a feature flag system emerges when you use flags as a progressive delivery control plane — gradually exposing changes, measuring impact, and responding to problems before they affect your entire user base. This post covers four battle-tested patterns and how to implement them with FeatureSignals.

Pattern 1: Canary Releases

A canary release deploys a new version of a service to a small subset of instances and routes a percentage of traffic to those instances. Feature flags complement canary deployments by controlling which code paths execute within the canary — you might canary a new database query behind a flag even though the service deployment is the same.

go
// Canary pattern: percentage rollout with monitoring
func (h *CheckoutHandler) Process(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()
    userID := r.Header.Get("X-User-ID")

    // Evaluate canary flag — 1% → 5% → 25% → 100%
    useNewPaymentFlow, _ := h.flags.BooleanValue(
        ctx, "new-payment-flow", false,
        openfeature.NewEvaluationContext(userID, nil),
    )

    var err error
    var result *PaymentResult

    if useNewPaymentFlow {
        result, err = h.newPaymentFlow(ctx, r)
        metrics.Inc("checkout.payment.new_flow")
    } else {
        result, err = h.legacyPaymentFlow(ctx, r)
        metrics.Inc("checkout.payment.legacy_flow")
    }

    // Compare error rates between flows in your dashboard
    if err != nil {
        metrics.Inc("checkout.payment.error")
        http.Error(w, "payment failed", http.StatusInternalServerError)
        return
    }

    json.NewEncoder(w).Encode(result)
}

Pattern 2: Ring-Based Deployments

Ring-based deployment exposes changes to progressively larger audiences: internal employees first, then beta testers, then early adopters, then general availability. Each ring is a segment in FeatureSignals, and the flag's targeting rules route users to the appropriate variation based on ring membership.

Pattern 3: Kill Switches

A kill switch is a feature flag that, when toggled, immediately disables a feature for all users — regardless of any other targeting rules. Kill switches take priority over all other rules in the evaluation engine (step 2 in our 9-step pipeline). They're the circuit breaker of your application: when a feature causes errors, degrades performance, or triggers an incident, you toggle the kill switch and the feature is instantly disabled without a deployment.

Pattern 4: A/B Experiments

A/B experiments use feature flags to randomly assign users to variants and track their behavior. FeatureSignals records impressions — records of which user saw which variant — and can forward them to your analytics pipeline. Combined with consistent hashing, users stay in the same variant throughout the experiment, ensuring a consistent experience.

Observability During Rollouts

Every progressive delivery pattern requires observability. You must know, in real time, whether the new code path is healthy. Instrument your flag evaluations with metrics that include the flag key and variation, and build dashboards that compare error rates, latency, and business metrics between flag variations. When the data shows the new variant is healthy, increase the rollout percentage. When it doesn't, kill the flag and investigate.