Schedule icon
Webhook icon
Parallel icon
Request icon
Script icon
Process icon
If icon
Upsert icon
SlackIncomingWebhook icon
Fail icon
Log icon

Multi-Region Failover Orchestrator with DNS Cutover

Probe three regions in parallel and cut Cloudflare DNS to a healthy secondary with post-switch verification and war-room alerts in Kestra.

Categories
CloudInfrastructure

How it works

  • synthetic_health_check (core.trigger.Schedule, every five minutes, ships disabled: true) and on_demand_failover (core.trigger.Webhook) both start the same runbook - scheduled detection plus an incident-channel escape hatch.
  • probe_regions (core.flow.Parallel) hits the primary, secondary, and tertiary health endpoints at the same time; each core.http.Request contributes a status code.
  • assess (scripts.python.Script, Process runner) turns the three codes into a verdict: only a dark primary with a live secondary sets cutover_needed, while primary AND secondary down sets cutover_blocked. Everything returns through Kestra's ::json:: outputs protocol.
  • cutover_gate (core.flow.If) routes the authorized path: switch_dns (cloudflare.dns.records.Upsert) republishes the record to failover_ip with a 60-second TTL, verify_failover re-checks the switched record, and verify_gate posts a war-room all-clear on 200 or pages hard and fails the execution through core.execution.Fail when verification fails.
  • The no-cutover path splits again: blocked_gate pages when both regions are down (an incident, not a healthy run), otherwise log_healthy writes one quiet line.
  • Any flow-level failure lands in Slack through the errors handler.

What you get

  • Parallel detection latency across three regions instead of serial probe chains.
  • An authorized, verified DNS cutover: the record moves only when the primary is dark AND the secondary is live, and the execution stays green only when the switched record actually serves 200.
  • War-room Slack messages carrying the degraded-region list and measured codes, plus core.execution.Fail so SLA dashboards and dependent flows see red after a broken cutover.
  • Outputs for primary_ok, healthy_regions, degraded_regions, healthy_count, cutover_performed, verified, and summary that downstream incident flows can gate on.

Who it's for

  • Platform and SRE teams running active-passive multi-region setups who want the failover step to be a reviewed, observable runbook instead of a stressed engineer typing dig and clicking through a DNS console at 3am.

Why orchestrate this with Kestra

  • Failover is exactly the kind of rare, high-stakes, multi-step action that goes wrong when it is manual: the probes, the authorization check, the record change, and the post-switch verification are four decisions that belong in a versioned flow with history, alerts, and a deliberate failure state - not in a runbook wiki.

Prerequisites

  • A Cloudflare-managed zone and an A (or AAAA) record for host_name.
  • A secondary region with a stable origin address reachable from users.
  • Health endpoints per region that return 200 when the region can serve traffic.

Secrets

  • CLOUDFLARE_API_TOKEN - token with DNS edit permission on the zone.
  • SLACK_WEBHOOK_URL - Incoming webhook used for cutover, critical, and error alerts.
  • FAILOVER_WEBHOOK_KEY - key guarding the on_demand_failover webhook.

Quick start

  • Set zone_id, failover_ip, and the three regional URLs; enable the schedule (or fire the webhook).
  • With everything healthy the execution logs cutover=none and exits green.
  • Point primary_url at a dead endpoint and re-run: the record flips to failover_ip, verification runs, and the war-room message reports the switch.

How to extend

  • Add a core.flow.Loop around switch_dns that also updates weighted records or a second hostname.
  • Follow a successful cutover with an auto-rollback flow on a timer (core.trigger.Schedule plus a cutover_performed output from this flow).
  • Feed degraded_regions into prometheus or incident-ticket tasks to open the problem record alongside the failover.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.