Skip to main content
This page is the reference companion to Control plane reliability. It documents the Helm values, cookie and URL strategies, identity provider (IdP) redirect URLs, database connection sizing, control plane statuses, and error codes for control plane reliability. For the setup procedure, see Configure control plane reliability. For day-2 operations, see Manage a control plane reliability group.

Helm values

Set these values in your Astronomer Helm values. controlPlaneHA.enabled and dataPlaneFailover.enabled are independent switches, so you can run control plane reliability without data plane failover, or the other way around.
Set astronomer.houston.upgradeDeployments.enabled under the astronomer subchart, as shown. A top-level houston.upgradeDeployments.enabled doesn’t take effect and silently leaves the hook enabled.
When you bring existing Astro Deployments under control plane reliability, you choose how their URLs and the session cookie are scoped. APC supports three strategies, all selected through Helm and DNS configuration on an APC 2.1.0 or later build. Pick one per installation.

Alias existing URLs

Option A is the recommended default for existing installations. Keep every Astro Deployment’s existing per-CP URL and add a parallel global-domain URL as an alias. Both resolve to the same Airflow webserver.
  • Enable: the default path. Set controlPlaneHA.enabled: true and globalBaseDomain. The ingress re-stamp adds the global-alias hosts alongside the per-CP ones.
  • Cookie: the session cookie is scoped to .<globalBaseDomain>, so it’s sent to Deployment Airflow subdomains under the global domain and single sign-on (SSO) works there. Per-CP hosts keep their own per-CP cookie.
  • Customer impact: none. Old per-CP URLs keep working, and global URLs are added. This is the safe default for existing customers.
With Option B, scope one session cookie to a common ancestor domain that covers both the global and per-CP host families, so a single cookie is sent to every host under that ancestor.
  • Enable: set helm.cookieDomain to the shared parent of your global and per-CP domains. The platform then runs in single-cookie mode, in which per-CP hosts mint the same wide cookie.
The cookie is sent to every host under the ancestor, including anything else hosted there. There is no platform guard against too broad an ancestor. You’re responsible for choosing one that covers only trusted Astronomer hosts, and for TLS covering those hosts. Choose Option B only if that broader exposure is acceptable.

Re-align URLs

Option C is for fresh installations only. Regenerate all Astro Deployment URLs under a single new shared parent domain, replacing the per-CP URLs rather than aliasing them.
  • Enable: install with the cluster base domain set to the shared parent so that every URL templates under it.
Because per-CP URLs are replaced rather than kept, any tooling that uses the old hardcoded URLs breaks. For that reason, Option C is supported only for fresh installations, never as a migration for existing customers.

Identity provider authentication and the OAuth redirect URL

To configure an external identity provider on a standard single-control-plane installation, see Integrate an authentication system. This section covers only what changes when you enable control plane reliability with controlPlaneHA.enabled: true. If you integrate an external identity provider (IdP), the redirect and callback URL you register with the IdP must point at the global domain, not a per-CP domain. Whenever controlPlaneHA.enabled: true, the APC API templates all customer-facing URLs — including the OAuth redirect_uri it hands to your IdP — from globalBaseDomain instead of the per-CP baseDomain. Register the values that use the global domain:
  • https://houston.<global-domain-name>/v1/oauth/redirect/ for the implicit flow, which is the default.
  • https://houston.<global-domain-name>/v1/oauth/callback/ for the code flow (auth.openidConnect.flow: "code").
Register whichever matches your configured flow, or both if you’re unsure, and keep the trailing / as the APC API emits it, because most IdPs match the redirect URI exactly. Customer sign-in and the IdP round trip run on the global hostname so that APC sets the session cookie, scoped to .<global-domain-name>, on a host that’s allowed to set it. A per-CP host is a sibling of the global domain, not a descendant, so a global-scoped cookie set there is dropped and the user is bounced back to the sign-in page. To enforce this, the APC API doesn’t serve customer auth paths on the per-CP admin hostnames: any OAuth start, IdP callback, or Deployment sign-in request that lands on a per-CP host is redirected to app.<global-domain-name>/login. The per-CP hostnames are for direct admin access only. There is no separate Helm value for the redirect URL. It follows the same globalBaseDomain resolution as every other customer-facing URL. The session cookie’s domain defaults to .<global-domain-name> and is overridable through helm.cookieDomain. See Widen the cookie scope.
When you migrate an existing installation to control plane reliability, if your IdP application was registered with a per-CP redirect URI, update it to the global-domain URI as part of enabling control plane reliability. Otherwise the IdP rejects the callback after sign-in once the APC API starts sending the global redirect_uri.
This section applies to bring-your-own OIDC and IdP setups. If you use the default shared Auth0 tenant that Astronomer provides, rather than your own external IdP, the redirect is fixed to https://redirect.astronomer.io regardless of domain, and this section doesn’t apply.

Database connection sizing

Every control plane shares one database, and each long-lived APC API Pod holds its own connection pool against it. As you add control planes or scale replica counts, total connections grow. Size the database’s max_connections, or cap the pools, accordingly, or you risk connection exhaustion.

Measured consumption

Measured on a two-control-plane installation with astronomer.houston.prismaConnectionLimit unset, so each Pod uses the default pool of about num_cpus × 2 + 1:
  • About four connections per long-lived Pod.
  • Long-lived, database-connected Pods per control plane at default replica counts, with control plane reliability and data plane failover enabled: two APC API, two APC API worker, three DP-Link, and three Navigator Pods, for 10 Pods and about 40 connections per control plane.
  • Observed total for two control planes: 84 connections (about 42 per control plane), almost all idle, against max_connections = 400 — about 21% utilized.
  • Short-lived hook and cron jobs (database migration, upgrade-deployments, control plane refresh, and cleanup) open a few more connections briefly while they run. Budget a small margin for these.

Capacity-planning formula

At default replica counts and default pool, pods_per_CP × pool_per_pod is about 40, so as a rule of thumb:
  • Budget about 40 connections per control plane, and set max_connections ≥ N_CPs × 40 × 1.25 for about 25% headroom.
  • At max_connections = 400, that leaves headroom for roughly five to six control planes at default sizing before you must intervene.
Recompute if you change replica counts or increase Pod CPU, because the default pool scales with CPU (num_cpus × 2 + 1 per Pod), so larger Pods open larger pools.

Levers for more headroom

  • Cap the per-Pod pool: set astronomer.houston.prismaConnectionLimit to a fixed, smaller value so that each Pod’s pool is bounded regardless of Pod CPU. This makes the total exactly predictable: N_CPs × pods_per_CP × prismaConnectionLimit.
  • Front the database with PgBouncer in transaction-pooling mode, so that many APC API Pods multiplex onto far fewer server-side connections. Astronomer recommends this once the control plane count or replica counts push you toward max_connections.
  • Raise max_connections on the managed database if the instance class allows it. Each connection costs memory, so scale the instance accordingly.
Before you add a control plane, check current utilization and keep it comfortably below the limit, aiming for 75% or less:

Control plane status reference

Health endpoint unhealthy reasons

The /controlplane/status endpoint evaluates the following reasons in order, and the first match wins:
  1. Not registered (NOT_REGISTERED).
  2. Cordoned (CORDONED).
  3. Decommissioned (DECOMMISSIONED).
  4. Region inactive (REGION_INACTIVE).
  5. Chart version behind the region maximum (VERSION_OUTDATED).
A transient database error also returns unhealthy for that single poll, and this result isn’t cached. Otherwise the endpoint returns 200. Results are cached for about 30 seconds. The endpoint doesn’t consider the last heartbeat — heartbeat staleness affects only the UI health dot, never routing.

Error codes

These are the GraphQL error codes the APC API returns when it rejects a mutation. They’re a separate set from the health-endpoint reasons in the previous section, which is why some names differ — for example, the health endpoint reports VERSION_OUTDATED while the matching mutation error is CP_VERSION_OUTDATED.