PostgreSQL 17 turns a logical replication slot into an object that can survive a primary promotion by synchronizing it to standbys, and configuring it correctly means aligning four things: failover = true at slot or subscription creation, sync_replication_slots = on, standby_slot_names on the primary, and hot-standby feedback on the standby. Miss any one and the slot either never syncs or syncs to a position the standby cannot honor, so this guide — part of Failover & Slot Recovery — specifies the exact settings, the pg_sync_replication_slots() mechanics, and the verification queries that prove a slot will actually fail over.
failover = true slot is copied to the standby by the sync_replication_slots worker; standby_slot_names keeps the synced slot's WAL retained so the promoted node resumes without a resnapshot.GUC and Attribute Semantics
Failover slots are governed by one slot attribute and three server parameters that must be consistent across the primary and its standbys. The attribute decides whether a slot is a candidate for synchronization; the GUCs decide whether the copy actually happens and stays valid. The table maps each to its guarantee and its failure mode.
| Setting | Where | Value | Guarantee / logical-replication behavior |
|---|---|---|---|
failover (slot / subscription) |
slot object | true |
Marks the slot for synchronization to standbys; a false slot is never copied and is lost on promotion |
sync_replication_slots |
standby | on |
Runs the background slot-sync worker that pulls failover slots from the primary on an interval |
standby_slot_names |
primary | physical slot name(s) | Primary refuses to send logical changes past what the named physical standbys have flushed, so the synced slot never references recycled WAL |
hot_standby_feedback |
standby | on |
Stops the primary vacuuming catalog rows the synced slot’s catalog_xmin still needs; without it a synced slot can be invalidated |
sync_replication_slots interval |
standby | internal | Sync is periodic, not per-commit; a manual pg_sync_replication_slots() forces an immediate copy before promotion |
The critical interaction is between standby_slot_names and the synced slot’s restart_lsn. A synchronized slot copies the primary’s restart_lsn, but that LSN is only usable on the standby if the standby actually holds the WAL from that point forward. standby_slot_names enforces exactly that ordering: the primary will not let a logical consumer’s changes — or the WAL trimming that follows — outrun the named physical standby, so the standby is always at or ahead of every synced logical slot’s needs. Leave it unset and the standby can recycle WAL the synced slot references, producing a slot that shows synced = true but is invalidated the moment you promote. The durability semantics of the slot itself, independent of failover, are catalogued in replication slot types.
Synchronization is periodic, not transactional, so the synced slot’s confirmed_flush_lsn on the standby always trails the primary’s by one sync interval plus whatever the physical stream lags. That trailing gap is normal and safe — after promotion the consumer simply replays the small window between the standby’s copied position and the true last-applied position, which an idempotent apply absorbs. What is not safe is a gap that grows without bound: if the sync worker stalls (for example because the standby fell out of standby_slot_names eligibility), the synced position freezes while the primary advances, and a promotion then forces a large replay or a resnapshot. Monitor the byte distance between the primary’s slot position and the standby’s synced copy the same way you monitor physical lag, and alert when it stops shrinking.
Diagnostic Patterns
Verify configuration on both nodes, because the primary and standby each hold half the mechanism. On the primary, confirm every production slot is a failover candidate and the physical target is named:
-- Primary: which logical slots will fail over, and is standby_slot_names set?
SELECT slot_name, failover, active, wal_status
FROM pg_replication_slots
WHERE slot_type = 'logical';
SHOW standby_slot_names; -- must name the physical slot the failover-target standby uses
On the standby, confirm the sync worker actually copied the slot and that it is reserved, not lost. synced = true with wal_status = 'reserved' is the healthy state; synced = true with wal_status = 'lost' means WAL retention failed and the slot will not survive promotion:
-- Standby: has the slot been synchronized and is its WAL still retained?
-- ALERT: synced = true but wal_status <> 'reserved' -> standby_slot_names/feedback misconfigured.
SELECT slot_name, synced, temporary, wal_status,
restart_lsn, confirmed_flush_lsn
FROM pg_replication_slots
WHERE slot_type = 'logical';
Check that hot-standby feedback is reaching the primary, since a synced slot’s catalog xmin depends on it:
-- Primary: is the standby sending feedback that protects the synced slot's catalog rows?
-- ALERT: backend_xmin NULL for the failover-target standby -> hot_standby_feedback likely off.
SELECT application_name, state, backend_xmin, sync_state
FROM pg_stat_replication;
Safe Deployment Sequence
Enable failover slots without disrupting the running stream by applying the reload-only settings first and adding the failover attribute deliberately.
1. Prepare the standby. Set hot_standby_feedback = on and sync_replication_slots = on, then reload. Both take effect without a restart.
-- On the standby.
ALTER SYSTEM SET hot_standby_feedback = 'on';
ALTER SYSTEM SET sync_replication_slots = 'on';
SELECT pg_reload_conf();
2. Retain WAL for the physical standby on the primary. Point standby_slot_names at the physical slot the failover-target standby streams through. Until this is set, do not treat any synced slot as recoverable.
-- On the primary. 'standby1' is the physical slot the failover target uses.
ALTER SYSTEM SET standby_slot_names = 'standby1';
SELECT pg_reload_conf();
3. Make each slot a failover candidate. New slots take failover = true at creation. Existing slots created without it must be recreated, because failover cannot be toggled on a live slot for a native subscription — recreate the subscription with the attribute, accepting the initial copy if needed.
-- New failover-enabled slot, created explicitly:
SELECT pg_create_logical_replication_slot('cdc_orders', 'pgoutput', false, false, true);
-- name plugin temp twophase failover
-- Or via a native subscription that requests failover on its own slot:
CREATE SUBSCRIPTION sub_orders
CONNECTION 'host=pg-primary dbname=analytics application_name=sub_orders'
PUBLICATION pub_orders
WITH (failover = true, copy_data = true, create_slot = true);
4. Force a sync and verify before trusting it. Synchronization is periodic, so trigger an immediate copy and confirm the standby shows the slot reserved.
-- On the standby: force an immediate copy, then verify.
SELECT pg_sync_replication_slots();
SELECT slot_name, synced, wal_status FROM pg_replication_slots WHERE slot_type = 'logical';
-- Expect: synced = true, wal_status = 'reserved'.
5. Revert cleanly if needed. To back out, disable the sync worker on the standby and unset the retention setting; the failover attribute stays on existing slots but simply stops being synchronized. None of these require a restart.
-- Revert (standby then primary):
ALTER SYSTEM SET sync_replication_slots = 'off'; SELECT pg_reload_conf(); -- standby
ALTER SYSTEM RESET standby_slot_names; SELECT pg_reload_conf(); -- primary
Pipeline Integration
Failover slots change how a consumer treats a promotion, so encode that in the reconnect logic. A consumer reading a failover = true slot can, after a promotion, reconnect to the new primary and find its slot already present at confirmed_flush_lsn, so the correct behavior is to resume — not to recreate a slot from scratch. Guard against the misconfiguration where the slot exists but is lost by checking wal_status on reconnect and falling back to the resnapshot path only then, the decision made explicit in recovering logical slots after primary failover.
# On reconnect after a promotion: trust a synced, reserved slot; resnapshot only if lost.
def recover_slot(conn, slot="cdc_orders"):
row = conn.execute(
"SELECT synced, wal_status FROM pg_replication_slots WHERE slot_name = %s",
(slot,),
).fetchone()
if row is None or row["wal_status"] == "lost":
return "resnapshot" # slot absent or invalidated -> rebuild
return "resume" # synced + reserved -> resume from confirmed_flush_lsn
Export synced and wal_status per slot into the same metrics stream the rest of the topology uses, and alert when a production slot reports failover = false or a synced slot leaves reserved — those are the two conditions that quietly re-introduce resnapshot risk. A Debezium connector benefits identically: with a failover-enabled slot present on the promoted node, it resumes from its committed Kafka offset instead of triggering a fresh snapshot.
Two deployment shapes deserve explicit handling. With multiple standbys, list every physical slot the failover targets stream through in standby_slot_names, not just the preferred one, so the synced slot stays resumable regardless of which standby the orchestrator promotes. With a cascading standby (a standby that streams from another standby rather than the primary), slot synchronization follows the same chain, but each hop adds latency to the synced position — keep the failover targets streaming directly from the primary where recovery-time objectives are tight. In both cases, run the standby-side verification query on every candidate node, because a slot that is synced and reserved on one standby proves nothing about the node the orchestrator actually chooses.
Authoritative references
- PostgreSQL 17: Replication configuration (
sync_replication_slots,standby_slot_names) — the canonical GUC definitions and their standby interactions. - PostgreSQL:
pg_sync_replication_slots()and replication management functions — the manual synchronization function and slot creation signatures. - PostgreSQL:
pg_replication_slotsview — thefailoverandsyncedcolumns used to verify configuration.
Related
- Recovering Logical Slots After Primary Failover — the runbook for when a slot did not survive despite this configuration.
- Failover & Slot Recovery — the parent guide covering switchover and recovery across all supported versions.
- Replication slot types — the durability and lifecycle semantics of the slots this feature synchronizes.