TILLARK · FAILOVER

Roles move. Machines don't lie about it.

PREVIEW

Failover is a state machine over roles, not machines: there is a primary role and a replica role, and they move between nodes. That single idea dissolves the “original vs backup” confusion at the heart of failback — and every dangerous transition is fenced, quorum-gated, and four-eyes approved.

01State machine

The failover / failback lifecycle

The reducer is a pure, tested core — illegal transitions are no-ops. It encodes the guardrails below directly, so “never promote without fencing” is a property of the machine, not a hope about the operator.

text
   ┌──────────┐  primary unhealthy for N sec across M observers
   │  HEALTHY  │  (≥1 observer positioned where the APP is)
   └────┬─────┘─────────────────────────────────────────────┐
        │ manual / auto (opt-in)                             ▼
        │                                             ┌──────────────┐
        │                                             │   SUSPECT     │
        │                                             │ confirm window│
        │                                             └──────┬───────┘
        ▼                                                    │ quorum agrees
 ┌──────────────┐  fence old primary                        │
 │   FENCING     │◀──────────────────────────────────────────┘
 └──────┬───────┘  STONITH / Neon suspend + role-password rotate
        │           pre-flight: REFUSE to promote a too-stale replica
        ▼
 ┌──────────────┐  promote replica → it holds the PRIMARY role;
 │  PROMOTED     │  repoint app (DNS flip default | proxy opt-in);
 └──────┬───────┘  backups now sourced from the new primary
        │ old node returns
        ▼
 ┌──────────────┐  old node re-attaches as REPLICA of the new primary
 │ REVERSE-SYNC  │  ⚠ NEVER resume the old direction (would overwrite
 └──────┬───────┘     new writes) · physical: pg_rewind · logical: re-seed
        │ lag → 0
        ▼
 ┌──────────────┐  DELIBERATE clean switchover: quiesce writes,
 │  FAILBACK     │  drain the last bytes, flip the role back.
 └──────────────┘  Catch-up FIRST, flip SECOND → zero data loss.
                   Failback is manual / scheduled — never auto (anti-flap).
02Guardrails

What the machine refuses to do

GuardrailWhat it prevents
Confirmation windowUnhealthy for N seconds across M observers — with at least one positioned where the app is, not only where TillArk is — so a network partition can’t trigger a false failover.
Fence before promoteThe old primary is fenced first, so it can’t keep accepting writes — no split-brain double-write.
QuorumA quorum of observers must agree the primary is gone before SUSPECT advances to FENCING.
Staleness boundA pre-flight check refuses to promote a replica that is beyond the allowed lag — you never promote a copy that’s missing too much.
Anti-flapA cooldown + a failover cap per window stops ping-pong; a promote already mid-flight blocks a second one.
Atomic-ish switchIf the DNS/proxy repoint half-fails, it rolls back rather than leaving traffic split.
03Fencing

Fencing — even a DB you don't control

Fencing (STONITH) makes the old primary stop accepting writes before a replica is promoted. On self-managed Postgres that’s Patroni + pg_rewind. On a managed database you don’t own — Neon, RDS, Supabase, PlanetScale — TillArk uses a provider-native substitute: rotate the role password and suspend the compute endpoint via the provider API, so the old primary rejects writes even if it is still alive.

Fencing itself is an authenticated, audited action; the commands the agent executes are hybrid-signed and mTLS-authenticated between agent and control plane. The fence_status (none → pending → fenced) is tracked on the failover row.

04Promote

Promote a replica

Full-auto failover is explicit opt-in, never the default. A manual promote is a high-privilege, RBAC-gated action that additionally requires four-eyes approval — the same discipline as a real restore.

bash
# Promote a replica. High-privilege + four-eyes: a DIFFERENT owner/admin
# approver and a reference. The server re-verifies the approver; a token
# can never approve its own promote.
tilldev ark failover promote --source <source-id> \
  --to <replica-node> \
  --approved-by <second-approver-uuid> --approval-ref INC-4821

# Watch the state + replica lag:
tilldev ark failover status --source <source-id>
#  state    fencing → promoted
#  ROLE     REGION   LAG(s)  PROMOTABLE  HEALTH
#  primary  eu-west  0       yes         healthy

On promotion the replica takes the primary role, the app is repointed (DNS flip by default, or an ark-managed proxy for enterprise, which removes the DNS-TTL wait), and backups are sourced from the new primary. Logical-replication caveats are handled — sequences are bumped past the primary on promote (or you use UUIDv7 / ULID and avoid a shared counter), and DDL is fanned to both sides through a TillArk-aware migration path.

05Failback

Failback: catch up first, flip second

When the old node returns it re-attaches as a replica of the new primary — the old direction is never resumed, because that would overwrite the writes taken during the outage. Only once the returning node’s lag reaches zero can you run a deliberate, scheduled failback: quiesce writes, drain the last bytes, then flip the role back. Failback is manual / scheduled — never automatic, to avoid flapping.

bash
# Failback is a deliberate, scheduled switchover — refused while the
# returning node is beyond the failback staleness bound.
tilldev ark failover failback --source <source-id> \
  --lag 0 \
  --approved-by <second-approver-uuid> --approval-ref CHG-1190
Zero-loss by construction
Failback catches up first and flips second. It is refused while the returning node is beyond the staleness bound, so a flip can never drop the writes that were taken on the new primary during the incident.
06Degrade safely

The agent can act if the control plane is down

The control plane going down must never take your ability to fail over with it. The agent caches its policy and last-known topology and can execute a pre-authorized failover while the control plane is unreachable — deferring entirely to the control plane whenever it is reachable. TillArk is never a single point of failure for your recovery.


Next: Security for the signed-command channel and the approval model, or Architecture for the three-tier topology behind failover. Back to the TillArk overview.