WAL segment not found / pg_receivewal

PostgreSQL Replication Slot Overflow: Quick Fix

Replication slots can fill your disk fast if a standby disconnects. Here's how to clear them and stop the bleeding.

Quick answer for pros

Check pg_replication_slots, look for slots with active = false. Drop them with SELECT pg_drop_replication_slot('slot_name');. Then set max_slot_wal_keep_size = -1 in postgresql.conf and reload. Done.

What's going on

Replication slots are great for ensuring a standby never misses WAL data. But if a standby goes down and doesn't come back, the slot holds on to all WAL files since it last connected. This eats disk space fast — I've seen a 500GB drive fill up in hours.

This usually happens after a network outage, a standby server crash that never recovers, or someone forgetting to drop a slot when decommissioning a replica. The PostgreSQL logs will show errors like WAL segment not found or the disk fills up until pg_wal hits 100%.

Step-by-step fix

  1. Identify the culprit slot. Run this on the primary:
    SELECT slot_name, active, pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) / 1024 / 1024 AS MB_held FROM pg_replication_slots;
    Look for slots where active is f and MB_held is huge.
  2. Drop the dead slot. Replace dead_slot with the actual name:
    SELECT pg_drop_replication_slot('dead_slot');
    This instantly frees all those WAL files. The disk space may take a minute to show free — check with df -h.
  3. Set a safety limit. Edit postgresql.conf and add:
    max_slot_wal_keep_size = 5GB
    This stops any single slot from hogging more than 5GB of WAL. Reload with pg_ctl reload or SELECT pg_reload_conf();.
  4. Restart replication if needed. If the standby is coming back, re-create the slot after it's connected:
    SELECT * FROM pg_create_physical_replication_slot('standby1');

What if dropping the slot doesn't free space?

Sometimes the WAL files are still referenced by a checkpoint. Run a manual checkpoint:

CHECKPOINT;
Then check pg_wal size again. If it's still huge, your disk might have a separate WAL archive location. Check archive_command in postgresql.conf — if it writes to a directory that's also filling up, clear that too.

Worst case: restart the PostgreSQL service. It triggers a clean checkpoint and releases stale WAL. But do this only during maintenance — it causes a brief outage.

How to stop this from happening again

Set max_slot_wal_keep_size to a sane value (like 5GB or 10GB) on every PostgreSQL 13+ instance. This is the simplest guard — it trims old WAL even if a slot is stuck.

Also monitor pg_replication_slots regularly. I use a simple cron job that alerts if any slot is inactive for more than 2 hours:

SELECT slot_name FROM pg_replication_slots WHERE NOT active AND pg_last_wal_receive_lsn() IS NOT NULL;

If you're on PostgreSQL 12 or older, you don't have max_slot_wal_keep_size. Upgrade, or set wal_keep_segments to a low number (like 500) and rely on archive_command for backups.

One last thing: never leave a replication slot lying around after decommissioning a standby. Always drop the slot before removing the replica. It's the #1 cause of this mess.

Related Errors in Database Errors
SQL Server Error 9002 SQL Server Log File Exploding? Stop It Now 0X00001A39 Fix Transaction Invalid Marshall Buffer Error 0x1A39 0X00001ABA Savepoint Fails with Open Files (0X00001ABA) ERROR 1055 (42000) Fix MySQL 1055: only_full_group_by error in 8.0

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.