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
1205 SQL Server Deadlock Victim: Why It Happens and How to Fix 1205 SQL Deadlock Chain Detected: Fix Steps 0X80110472 Fix COMADMIN_E_REGDB_NOTINITIALIZED (0X80110472) Fast 1064 MySQL Error 1064 on INSERT: Missing Quotes Around Strings

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.