Skip to main content
Per-deployment migration moves one or more individual Astro Deployments from one data plane cluster to another, without failing over the whole cluster. It is available in Astro Private Cloud (APC) 2.1 and later. Per-deployment migration is an extension of data plane failover. It has no separate license, feature flag, or Helm value of its own: if you enabled data plane failover on your clusters, per-deployment migration is enabled too. Where the 2.0 feature only failed over an entire cluster at once, per-deployment migration lets you move a chosen subset of Deployments while everything else stays in place. Two things typically drive its use:
  • Rebalancing: move a single busy or unhealthy Deployment onto a neighboring cluster without disturbing anything else on either cluster.
  • Per-team failover drills: when different teams own different Deployments on the same cluster, cluster-level failover forces every team into one coordinated window. Per-deployment migration lets each team validate failover on their own Deployments, on their own schedule.
Under the hood, a migration is the same machinery as a cluster failover: one mission per Deployment, moving through the same flight sequence. What differs is the entry point — you pick the Deployments — and one hard constraint.
Migration is in-region only. A Deployment can only be migrated to a cluster in the same region as its current cluster, and this is enforced, not advisory.Per-deployment migration moves the Deployment, not its Airflow metadata database. A Deployment moved across a region boundary keeps talking to its metadata database in the original region, which adds cross-region database traffic on every scheduler tick. The latency cost is permanent and produces no error: the Deployment comes up healthy and simply runs slowly. To move workloads across regions, use full-cluster data plane failover, which is sequenced with your database promotion.
Enforcing that constraint is what most of the configuration work is about. The migration gate compares the region assigned to the source cluster against the region assigned to the destination cluster, so before you can migrate anything, every participating cluster needs a real region assigned to it. That region model is new in 2.1 and is the main configuration task. This guide covers the setup. For day-2 operations, see Manage and observe per-deployment migration. For the reference tables this guide links to — cluster failover states, configuration settings, and permissions — see Per-deployment migration reference.

Prerequisites

Per-deployment migration inherits every prerequisite of data plane failover. None of them are new in 2.1: if you already run data plane failover, you already have them. Confirm the following before you configure regions.

Step 1: Confirm data plane failover is enabled

Per-deployment migration ships with data plane failover, so there is no additional switch. On each participating data plane cluster, your APC Helm values must contain:
On the control plane:
Data plane failover requires split mode — a separate control plane (global.plane.mode: control) and data plane (global.plane.mode: data). It isn’t supported in unified mode (global.plane.mode: unified). global.dataPlaneFailover.enabled is the primary switch, and what it turns on depends on the plane’s mode:
  • On a data plane, it enables the data plane execution components (Pilot and Flightdeck) and the data plane internal API’s StartFlight remote procedure call.
  • On a control plane, it enables Navigator and the APC API dispatcher.
For the full enablement procedure, see Enable data plane failover.
Enabling the Helm value is necessary but not sufficient. Setting dataPlaneFailover.enabled makes a cluster failover-capable. The control plane then independently evaluates whether the cluster is actually failover-enabled by checking ESO configuration, Deployment types, and whether you upgraded every Deployment for failover. A cluster can stay capable-but-not-enabled indefinitely.Check the Failover field on the cluster detail page, or query Cluster.failoverEnabled, to see the effective state. Only failover-enabled clusters can be chosen as a migration destination. See Cluster failover states.

Step 2: Create your regions

A region is a control plane record — a name and a cloud provider — that clusters are assigned to. Regions are what the migration gate compares. You manage them on the Regions admin page in the APC UI, or through the GraphQL API. Regions are new in 2.1.

Seeded regions

The 2.1 schema migration creates two region rows automatically: You do not need to take any action for the upgrade to succeed — existing clusters are backfilled automatically and nothing breaks. But until you replace unset with a real region, every migration attempt involving that cluster is skipped with CLUSTER_REGION_NOT_SET.

Create a region in the APC UI

In the APC UI, go to Regions in the admin sidebar and select Create Region. A region needs two values:
  • Name must be unique across the installation. Use whatever names match how you reason about your topology, for example us-east-1, eu-west, or dc-chicago. The control plane doesn’t interpret the name — the gate compares region identity, not name strings.
  • Cloud Provider, for example aws, gcp, azure, or local. This isn’t cosmetic: a cluster can only be assigned to a region whose cloud provider matches the cluster’s own. See Step 3.
The page lists every region with its cloud provider and creation date, and offers Edit, Delete, and Activate per row.
The Regions admin page listing the two seeded regions
The Create Region dialog with the Name and Cloud Provider fields
The Cloud Provider dropdown in the Create Region dialog
The Regions page is shared with control plane high availability, where exactly one region is active at a time and activating a region switches control plane traffic. That has no bearing on data plane migration. The migration gate compares region assignment only — it never reads a region’s active state. The two seeded regions ship inactive, which is correct: an inactive region is a valid home for data plane clusters. If you aren’t running control plane high availability, ignore the Active column.

Create a region with the API

Save the returned region.id — you need it to assign clusters in Step 3. For the full region query and mutation surface, see Per-deployment migration reference.
A region’s cloudProvider is immutable while clusters are assigned to it. updateRegion rejects a cloudProvider change while any cluster references the region, and deleteRegion fails while any cluster is still assigned — reassign those clusters first. This prevents a region edit from silently orphaning its clusters. Name-only edits, and re-saving the same provider, are unaffected.

Step 3: Assign a region to every failover-enabled cluster

This is the step that unlocks migration. Every cluster you want to migrate a Deployment from, and every cluster you want to migrate one to, needs a real, non-unset region.

Assign a region to an existing cluster

  1. In the APC UI, go to Clusters in the admin sidebar and open the cluster you want to assign.
    The data plane clusters list in the APC UI
  2. Turn on Edit. The cluster form includes an Assigned Region dropdown next to Cloud Provider, and a read-only Failover field.
    The cluster page in edit mode, showing the Assigned Region dropdown and the Failover status field
  3. (Optional) If the cluster’s Cloud Provider is incorrect, correct it first. Assigned Region lists only the regions whose cloud provider matches the cluster’s.
    Editing the Cloud Provider field on the cluster edit form
    The Assigned Region dropdown filtered to regions that match the cluster's cloud provider
  4. In Assigned Region, select the region the cluster physically lives in.
    A cluster with its cloud provider and assigned region both updated
  5. Select Update Cluster. Review the old and new values in the Confirm cluster configuration update dialog, then select Confirm update.
    The Confirm cluster configuration update dialog listing the old and new values for Assigned Region and Cloud Provider
To do the same with the API:
Passing regionId: null clears the assignment.

Assign a region to a new cluster

Cluster registration accepts regionId directly, and the registration form includes the same region selector. At registration, the cluster inherits the assigned region’s cloudProvider, so there is no separate provider to set and no mismatch to resolve. With no region assigned, the provider comes from the data plane metadata, defaulting to local.

Cloud-provider consistency

When you edit an existing cluster’s assigned region, the region must share the cluster’s own cloudProvider. The cluster edit form’s Cloud Provider field is editable and filters the Assigned Region dropdown to matching regions; to switch provider, set the provider and a matching region together. The comparison is case-insensitive, so aws and AWS match. If the providers don’t match, the save is rejected:
If the region ID doesn’t exist:
Because every region belongs to exactly one cloud provider, region equality implies provider equality — the migration gate gets cross-provider protection without a second check. Keeping cluster.cloudProvider and region.cloudProvider in agreement is what makes that inference sound.
If a cluster’s own cloudProvider is empty, the consistency check is skipped and any region is accepted. This is intentional, so that on-premises and older clusters aren’t blocked, but it means the check is a guardrail rather than a guarantee.
Nothing forces a failover-enabled cluster to have a real region. A cluster can be fully failover-enabled, pass every health check, and still sit on the unset sentinel: registration succeeds, edits succeed, and cluster-level failover works normally. The consequence surfaces only at migration time, as a per-Deployment skip with CLUSTER_REGION_NOT_SET.Audit your clusters after upgrading to 2.1. Any failover-enabled cluster still on unset is a migration that silently does nothing the first time someone tries it.

Step 4: Verify the configuration

Run these checks before you declare the setup done.
  1. Confirm every failover-enabled cluster has a real region. In the APC UI, check the region on each cluster, or list regions with the API and confirm no participating cluster is assigned to unset:
  2. Confirm the destination cluster is failover-enabled and healthy. On the cluster detail page, the Failover field should read Enabled and the health dot should be green. With the API, Cluster.failoverEnabled should be true.
  3. Ask the control plane which destinations it considers valid:
  4. Do a canary migration. Migrate one low-stakes Deployment to the destination, and back, before you move anything that matters. See Manage and observe per-deployment migration.
failoverTargetClusters is broader than the migration gate. It filters on active status, failoverEnabled, data plane health, and no in-flight failover already targeting the cluster — but it doesn’t filter by region and does not exclude cordoned clusters. A cluster can appear in this list and still be rejected by migrateDeployments with DESTINATION_CLUSTER_CORDONED, or have every Deployment skipped with CROSS_REGION_MIGRATION_NOT_ALLOWED. The APC UI destination picker draws from this same query, so it inherits the same gaps: each option shows the cluster’s region so you can check it, but a cross-region pick fails at submit. Treat both the query result and the picker as a candidate list, not a guarantee.

Why migration is in-region only

A cluster-level failover and a per-deployment migration look similar but move different things: Because migration doesn’t touch the database, a cross-region migration would leave the Deployment’s scheduler, workers, and triggerer in one region while its metadata database stays in another. The Airflow scheduler queries its metadata database on every scheduling loop, so this adds cross-region round-trip latency to the hottest path in the system. Throughput drops, and nothing in the platform reports an error, because from Airflow’s point of view everything is working. To move across regions, use full-cluster data plane failover, sequenced after your database promotion. Cross-provider moves at the Deployment level are out of scope.

Backward compatibility and rollout

The move from “region is optional and ignored” to “region is required for migration” is phased so that upgrading to 2.1 breaks nothing. The 2.1 upgrade does the following automatically:
  • Adds cloudProvider to the region record.
  • Seeds the onprem and unset regions.
  • Backfills every cluster with no region to unset.
  • Ships the Regions admin page and the cluster region selector.
  • Makes migrateDeployments available, skipping any Deployment whose source or destination cluster is still on unset, with CLUSTER_REGION_NOT_SET.
After upgrading, you should:
  1. Create regions that reflect your real topology.
  2. Reassign every failover-enabled cluster off unset.
  3. Canary-migrate one Deployment per region pair to validate.