High Availability

PostgreSQL 17 Logical Replication: Failover Slots and Row Filtering

Logical replication in PostgreSQL has a critical gap: slots do not survive failover. PostgreSQL 17 finally fixes this with failover slots, plus adds row and column filtering for selective replication.

JusDB Team
June 10, 2025
Updated June 20, 2026
8 min read

A healthcare platform running Debezium CDC on PostgreSQL had a recurring nightmare: every primary failover caused their CDC pipeline to lose position and require a full re-snapshot of their 2TB patient events table. The re-snapshot took 6 hours and blocked all CDC consumers during that time. After upgrading to PostgreSQL 17 and switching to failover-enabled replication slots, their next planned failover completed in 90 seconds with zero CDC pipeline disruption.

PostgreSQL 17 ships two major logical replication improvements: failover slots that survive primary switchover, and row/column filtering for selective replication. This guide covers both.

TL;DR
  • Logical replication failover slots in PG17 survive physical replication failover — no more full re-snapshots after HA events.
  • Row filtering allows publishing only rows matching a WHERE clause — reduce replication traffic and consumer load.
  • Column filtering publishes only specific columns — useful for sensitive data exclusion and bandwidth reduction.
  • Failover slots require sync_replication_slots = on on all standbys.

The Slot Failover Problem

Before PostgreSQL 17, logical replication slots existed only on the primary. When a standby was promoted:

  1. The slot was gone — it existed only on the old primary
  2. The subscriber (Debezium, pglogical) lost its WAL position
  3. Full re-snapshot was required to restart the pipeline
  4. For large tables, this meant hours of downtime for downstream consumers

Creating Failover Slots in PostgreSQL 17

sql
-- Enable slot synchronization on the primary
ALTER SYSTEM SET sync_replication_slots = on;
SELECT pg_reload_conf();

-- Create a logical replication slot with failover enabled
SELECT pg_create_logical_replication_slot(
  'cdc_orders_pipeline',  -- slot name
  'pgoutput',             -- plugin
  false,                  -- not temporary
  true                    -- failover = true (new in PG17)
);

-- Verify the slot is synced to standbys
SELECT slot_name, slot_type, failover, confirmed_flush_lsn,
  pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn) AS lag_bytes
FROM pg_replication_slots WHERE failover = true;
Warning

Failover slots only work with physical streaming replication standbys — not with logical replicas. Ensure primary_slot_name is configured on standbys for full synchronization.

sql
-- On each standby: verify slot is synchronized
SELECT slot_name, synced, failover, confirmed_flush_lsn
FROM pg_replication_slots WHERE failover = true;

Row Filtering in Publications

PostgreSQL 17 allows publishing only rows matching a WHERE clause, dramatically reducing replication volume for tables with high write rates but where subscribers only need a subset of rows:

sql
-- Publish only completed orders (not pending/processing)
CREATE PUBLICATION orders_completed_pub FOR TABLE orders
  WHERE (status = 'completed' AND total_amount > 0);

-- Publish only recent events (last 90 days rolling)
CREATE PUBLICATION recent_events_pub FOR TABLE events
  WHERE (created_at > now() - INTERVAL '90 days');

-- Alter existing publication to add row filter
ALTER PUBLICATION orders_pub FOR TABLE orders
  WHERE (region = 'US' AND status != 'cancelled');
Tip

Row filters are evaluated on the primary before data is sent to subscribers. For tables where 80% of rows are irrelevant to downstream consumers, row filtering can reduce replication WAL traffic by 60-80%.

Column Filtering in Publications

sql
-- Publish only non-PII columns
CREATE PUBLICATION orders_analytics_pub FOR TABLE orders
  (id, product_id, quantity, total_amount, status, created_at);
-- Excludes: customer_email, shipping_address, payment_method

-- Combine row and column filtering
CREATE PUBLICATION orders_region_pub FOR TABLE orders
  (id, region, total_amount, status)
  WHERE (region IN ('US', 'EU'));

Monitoring Logical Replication Health

sql
-- Check replication slot lag (catch up before failover)
SELECT slot_name, pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn) AS lag_bytes,
  failover, active
FROM pg_replication_slots WHERE slot_type = 'logical';

-- Check subscription status on subscriber
SELECT subname, subenabled, subpublications,
  pg_wal_lsn_diff(latest_end_lsn, received_lsn) AS pending_bytes
FROM pg_stat_subscription;

-- View worker stats
SELECT subname, worker_type, last_msg_receipt_time,
  latest_end_lsn, last_msg_send_time
FROM pg_stat_subscription_stats;
Key Takeaways
  • Enable sync_replication_slots = on and create slots with failover = true before your next HA event — not after.
  • Row filtering reduces replication volume and subscriber processing load — apply it to any table where consumers only need a subset of rows.
  • Column filtering enables PII exclusion at the replication layer without application changes.
  • Monitor slot lag continuously — a lagging slot accumulates WAL on the primary and can cause disk exhaustion.

Working with JusDB on PostgreSQL Replication

JusDB designs logical replication pipelines for CDC, analytics offloading, and cross-region data distribution. We have built Debezium pipelines on PostgreSQL 17 failover slots that survived planned HA events with zero re-snapshot requirements.

Explore JusDB PostgreSQL Consulting →  |  Talk to a DBA

Share this article

JusDB Team

Official JusDB content team

Keep reading

MySQL Group Replication (2026): Multi-Primary HA, Conflict Resolution & Production Setup

Production-ready MySQL Group Replication deployment guide. Learn cluster sizing, monitoring setup, performance tuning, and disaster recovery planning.

MySQL5 minMay 13, 2026
Read

MariaDB Galera Cluster Production Guide: Mariabackup, MaxScale & Schema Strategy

Production MariaDB Galera Cluster: mariabackup-based SST, MaxScale Galera-aware routing, schema-change strategy with TOI vs RSU, and a troubleshooting playbook for the failures that actually take down production.

MySQL17 minMay 3, 2026
Read

Patroni with Consul DCS: PostgreSQL HA Without etcd

Configure Patroni to use Consul instead of etcd as its DCS for PostgreSQL HA. Covers Consul setup, patroni.yml, service discovery, HAProxy routing, and failover testing.

PostgreSQL10 minMar 5, 2026
Read