mirror of
https://github.com/magnus919/agent-skills.git
synced 2026-09-17 06:26:31 +03:00
cd14da26cc
Add a one-tool PostgreSQL operations skill: configuration review, index and query-plan analysis, vacuum/bloat, WAL archiving + point-in-time recovery, replication/failover, extensions, upgrades, and evidence-based diagnostics. Ships the read-only pgdiag collector (stdlib, --json, --plan-for, --help without a cluster), 9 dated references, tests, a human README, 6 eval cases, and the top-level index + regenerated catalogs. Routes app data access to backend-engineering and schema design to data-architect/data-engineering. Closes #245 Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
87 lines
3.6 KiB
Markdown
87 lines
3.6 KiB
Markdown
# Replication and Failover
|
|
|
|
> **Last Updated:** 2026-08-03
|
|
|
|
This reference covers streaming replication setup, monitoring, and the
|
|
failover runbook. Replication topology design (sync vs async, quorum, cluster
|
|
managers) is an architecture decision; this skill owns the PostgreSQL
|
|
mechanics and their verification.
|
|
|
|
## Streaming replication model
|
|
|
|
A standby connects to the primary with a replication slot, receives WAL
|
|
segments as they are produced, and replays them. `wal_level = replica` (or
|
|
higher) and `max_wal_senders`/`max_replication_slots` must be sized for the
|
|
number of standbys.
|
|
|
|
Setup essentials:
|
|
|
|
- Create a physical replication slot per standby
|
|
(`SELECT pg_create_physical_replication_slot('standby-1');`).
|
|
- Build the standby with `pg_basebackup -X stream` and configure
|
|
`primary_conninfo` in `postgresql.conf` (12+) with `standby.signal`.
|
|
- Confirm the standby is actually streaming: it is `in_recovery` and appears
|
|
in `pg_stat_replication` on the primary.
|
|
|
|
## Measuring replication health
|
|
|
|
```sql
|
|
-- On the primary: who is streaming and how far behind
|
|
SELECT application_name, state, sync_state, client_addr,
|
|
sent_lsn, write_lsn, flush_lsn, replay_lsn, replay_lag
|
|
FROM pg_stat_replication;
|
|
|
|
-- On the standby: is it receiving and replaying?
|
|
SELECT pg_is_in_recovery(), pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();
|
|
```
|
|
|
|
The `pgdiag` `recovery` and `replication` checks report both views.
|
|
|
|
Health rules of thumb:
|
|
|
|
- `state = streaming` for every standby; anything else (`startup`,
|
|
`catchup`, `backup`) is transitional or stuck.
|
|
- Lag should stay within the agreed bound. `replay_lag` measures the gap
|
|
between the primary's current WAL and what the standby has replayed.
|
|
- A slot that is far behind but still `streaming` means the standby cannot
|
|
keep up or the network is saturated — the slot's retained WAL grows on the
|
|
primary until it does.
|
|
|
|
## Synchronous versus asynchronous
|
|
|
|
- Asynchronous (default): the primary commits without waiting; failover can
|
|
lose the most recent commits.
|
|
- Synchronous (`synchronous_standby_names = 'standby-1'`): the primary waits
|
|
for that standby's flush before acknowledging commits. Trade-off: commit
|
|
latency for a durability guarantee.
|
|
- Choose deliberately and document the choice; the failover runbook must
|
|
state what durability was promised.
|
|
|
|
## Failover runbook
|
|
|
|
A failover plan names: who promotes, how clients are redirected, what happens
|
|
to the old primary when it returns, and how the result is verified.
|
|
|
|
1. **Confirm the directive**: failover is a mutation; it requires an explicit
|
|
human decision naming the target standby.
|
|
2. **Check lag and timeline first**: how much data is at risk, and has the
|
|
standby been applying continuously? Promotion with a lagging standby is a
|
|
deliberate data-loss decision, not an accident.
|
|
3. **Promote**: `pg_ctl promote` or `SELECT pg_promote();` on the chosen
|
|
standby. With a cluster manager (Patroni, repmgr) use its switchover
|
|
command instead of manual promotion.
|
|
4. **Redirect clients**: DNS, connection strings, or the pooler — verify a
|
|
fresh connection lands on the new primary and writes succeed.
|
|
5. **Rejoin the old primary** as a standby with `pg_rewind` (it is now
|
|
diverged from the new primary's timeline) — never let two primaries accept
|
|
writes.
|
|
|
|
## Hard boundaries
|
|
|
|
- Never promote without a human directive and a stated rollback path.
|
|
- Never let two primaries run: the old primary must be fenced or rejoined
|
|
before it can accept writes again.
|
|
- Never fail over to a standby with unknown lag and call it "the same data".
|
|
- Never disable `archive_mode`/WAL sending to "simplify" replication — the
|
|
archive and the stream are both part of the recovery story.
|