Summary
Implement planned/graceful primary switchover for PostgreSQL. Currently only unplanned failover (dead primary detection → promotion) is supported. This adds the ability to gracefully demote a running primary and promote a designated standby with zero data loss.
Motivation
Operators need planned switchover for maintenance windows, version upgrades, and host migrations. The MySQL path already supports this via graceful-master-takeover / graceful-master-takeover-auto — PostgreSQL should have parity.
Design
See docs/superpowers/specs/2026-04-18-postgresql-graceful-switchover-design.md for the full spec.
New instance operations (go/inst/instance_topology_postgresql.go):
PostgreSQLSetReadOnly — ALTER SYSTEM + pg_reload_conf + pg_terminate_backend
PostgreSQLGetCurrentWALLSN — pg_current_wal_lsn()
PostgreSQLWaitForStandbyLSN — poll pg_last_wal_replay_lsn() until caught up
PostgreSQLRepositionAsStandby — ALTER SYSTEM SET primary_conninfo for demoted primary
Switchover orchestration (go/logic/topology_recovery_postgresql.go):
PostgreSQLGracefulPrimarySwitchover — full flow: validate → pre-hooks → set read-only → wait catch-up → promote → reconfigure standbys → reposition demoted primary → post-hooks
CLI/API dispatch (go/logic/topology_recovery.go):
- Provider check in
GracefulMasterTakeover() dispatches to PostgreSQL path when cluster is PostgreSQL
- Same commands/endpoints:
graceful-master-takeover, graceful-master-takeover-auto
Key decisions:
- Demoted primary restart is operator's responsibility via
PostGracefulTakeoverProcesses hooks
- No
pg_rewind needed — primary is read-only before switchover, so no timeline divergence
- Separate implementation function (not branching in MySQL code) — follows existing pattern
Test Plan
Summary
Implement planned/graceful primary switchover for PostgreSQL. Currently only unplanned failover (dead primary detection → promotion) is supported. This adds the ability to gracefully demote a running primary and promote a designated standby with zero data loss.
Motivation
Operators need planned switchover for maintenance windows, version upgrades, and host migrations. The MySQL path already supports this via
graceful-master-takeover/graceful-master-takeover-auto— PostgreSQL should have parity.Design
See
docs/superpowers/specs/2026-04-18-postgresql-graceful-switchover-design.mdfor the full spec.New instance operations (go/inst/instance_topology_postgresql.go):
PostgreSQLSetReadOnly— ALTER SYSTEM + pg_reload_conf + pg_terminate_backendPostgreSQLGetCurrentWALLSN— pg_current_wal_lsn()PostgreSQLWaitForStandbyLSN— poll pg_last_wal_replay_lsn() until caught upPostgreSQLRepositionAsStandby— ALTER SYSTEM SET primary_conninfo for demoted primarySwitchover orchestration (go/logic/topology_recovery_postgresql.go):
PostgreSQLGracefulPrimarySwitchover— full flow: validate → pre-hooks → set read-only → wait catch-up → promote → reconfigure standbys → reposition demoted primary → post-hooksCLI/API dispatch (go/logic/topology_recovery.go):
GracefulMasterTakeover()dispatches to PostgreSQL path when cluster is PostgreSQLgraceful-master-takeover,graceful-master-takeover-autoKey decisions:
PostGracefulTakeoverProcesseshookspg_rewindneeded — primary is read-only before switchover, so no timeline divergenceTest Plan