Loop icon
Request icon
Sleep icon
Query icon
If icon
Create icon
SlackIncomingWebhook icon
Fail icon
Webhook icon

Feature-Flag Progressive Delivery with an Error-Rate Guard

Ramp feature flags safely in Kestra: each rollout stage waits, checks Prometheus error rates, and auto-disables the flag and opens an issue on breach.

Categories
Infrastructure

Diagram unavailable

We could not build the topology for this blueprint. The flow itself is valid, use the YAML on the left to run it.

Feature flags give you a release switch, but a switch is not a rollout strategy. Someone flips the flag to 100 percent, the error rate climbs, and the rollback conversation happens in a channel while customers are already affected. Progressive delivery fixes the shape: small percentages, real observation, and an automatic stop. This blueprint makes the ramp itself a workflow - each stage is one loop iteration that sets the flag, waits for genuine traffic, measures the error rate, and either advances or kills the flag and opens a ticket.

How it works

  1. ramp_stages (io.kestra.plugin.core.flow.Loop) iterates over your ramp_percentages input - by default 10, 25, 50, 100.
  2. set_stage (io.kestra.plugin.core.http.Request, PATCH with Bearer {{ secret('FLAG_API_TOKEN') }}) sends the LaunchDarkly-style JSON-patch that turns the flag on at that percentage; adapt the path and body to Unleash or any OpenFeature provider.
  3. observe_stage (io.kestra.plugin.core.flow.Sleep) holds for observation_minutes so the stage is judged on real user traffic, not on the deploy moment.
  4. error_rate_check (io.kestra.plugin.prometheus.Query, FETCH_ONE) computes the 5xx ratio for the flagged traffic over the last five minutes as a single scalar.
  5. guard (io.kestra.plugin.core.flow.If) compares it against max_error_rate. On breach: disable_flag PATCHes the flag off and to zero percent, open_issue (io.kestra.plugin.github.issues.Create) files a labeled ticket with the stage and the rate, alert_slack notifies, and fail_ramp (core.execution.Fail) stops the execution - the flow-level errors handler repeats the reason to Slack for anyone watching the release channel.
  6. If every stage holds, announce_full_rollout posts the completed ramp as a single green message.

What you get

  • A ramp that stops itself: flag off, issue filed, pipeline halted - no human in the critical path of a bad release.
  • One guard cycle per stage with the measured rate recorded in the execution history.
  • Event-driven entry: the flag provider's own webhook starts the ramp.
  • flag, stages_planned, and ramp outputs for release dashboards.

Who it's for

  • Platform teams standardizing how flags go from off to fully on across services.
  • SREs who want error budgets enforced during rollouts, not reviewed afterwards.
  • Product engineering teams shipping behind flags without a dedicated release engineer.

Why orchestrate this with Kestra

Ramps usually live in CI scripts that cannot wait an hour without burning runners, or in cron glue that hides its state. Kestra gives the ramp durable waits, an execution per rollout with every stage's verdict as history, native plugin tasks for Prometheus and the flag API, and a failure path that disables the flag instead of just turning red.

Prerequisites

  • A flag provider with a REST API and webhook events (LaunchDarkly, Unleash, or an OpenFeature edge); the PATCH body shown is the LaunchDarkly JSON-patch shape.
  • Prometheus scraping your service with a flag label (or adapt the selector) exposing http_requests_total.
  • A Kestra instance and a GitHub repository for abort issues.

Secrets

  • FLAG_API_TOKEN: token with flag-write access for the target environment.
  • PROMETHEUS_URL: base URL of the Prometheus server, e.g. http://prometheus:9090.
  • SLACK_WEBHOOK_URL: Slack incoming webhook for abort and success messages.
  • GITHUB_TOKEN: token with issue-write access to the repository input.

Quick start

  1. Add the four secrets above and replace the webhook key with a strong random value.
  2. Point flag_api_url at your provider's flag endpoint and set flag_key / flag_environment.
  3. Adapt the PromQL selector to your flag label if it differs.
  4. Call the webhook from the flag provider (or curl it) and watch one full ramp - stage, sleep, query, verdict.
  5. Force a breach (point the query at a noisy service, or drop max_error_rate to 0) and confirm the flag disables, the issue appears, and the execution fails.

How to extend

  • Guard latency too: add a second prometheus.Query on a p99 histogram and require both to pass in the guard condition.
  • Multi-flag release train: wrap this flow in a Subflow loop over a JSON list of flag keys.
  • Deployment-level rollback: in the then branch, add a Kubernetes rollout undo or Argo CD sync task before fail_ramp for flags that ship new binaries, not just config.
  • Gradual confidence: after the ramp, chain a disabled daily schedule that keeps the flag at 100 percent under the same error-rate guard until release sign-off.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.