Symptoms
Conditions:
- PostgreSQL log:
PANIC: could not write to file "pg_wal/..."withNo space left on device - All connections abruptly dropped
df -hshows 100% on the WAL partition (or data partition if they share)- PostgreSQL will not restart until space is freed
- Inactive replication slots are often the cause of pg_wal growth
Environment
Difficulty: Advanced | PostgreSQL versions: 12, 13, 14, 15, 16, 17
Root Cause
- The only safe immediate action when pg_wal is full: free space by dropping inactive replication slots — do NOT delete files from pg_wal manually.
max_wal_sizecontrols checkpoint frequency, not disk usage when replication slots hold WAL.max_slot_wal_keep_size(PG13+) is the prevention: limits WAL a slot can retain before it's invalidated.- After freeing space, PostgreSQL recovers automatically on restart — crash recovery replays the WAL.
- If both
pg_walandpg_baseare on the same volume, temp files or table growth may also fill it. - Never set
wal_keep_sizehigh without also settingmax_slot_wal_keep_size.
Free space by dropping inactive replication slots. Set max_slot_wal_keep_size to prevent recurrence. Restart PostgreSQL — crash recovery is automatic.
Investigation
-- BEFORE restart (investigate cause):
-- df -h $PGDATA ← is disk actually full?
-- du -sh $PGDATA/pg_wal/ ← WAL directory size
-- ls $PGDATA/pg_wal/*.history ← timeline files
-- du -sh $PGDATA/pg_wal/*.* | sort -h | tail -20
-- Check replication slots (common culprit):
SELECT slot_name, active, wal_status,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flushed_lsn))
AS retained_wal
FROM pg_replication_slots
ORDER BY confirmed_flushed_lsn;
-- inactive slots with large retained_wal = cause of disk full Fix Now
Free space by dropping inactive replication slots. Set max_slot_wal_keep_size to prevent recurrence. Restart PostgreSQL — crash recovery is automatic.
Related & next steps
Concepts on this page
Thanks — noted. This helps keep the database accurate.