Tuning the Write-Ahead Log (WAL) settings in PostgreSQL balances durability, replication requirements, and write performance. Correct values reduce checkpoint I/O spikes, keep standby servers from falling behind, and prevent WAL growth from exhausting storage.
PostgreSQL records changes in WAL before modifying data files, which enables crash recovery and powers physical and logical replication. WAL is written into the /pg_wal directory under the cluster data directory, and completed WAL segments are recycled when possible. Settings such as max_wal_size, min_wal_size, and checkpoint_timeout control how frequently checkpoints occur, while wal_level determines how much information is logged for replication and decoding.
Increasing WAL retention consumes disk space and can hide downstream problems (slow disks, replication lag) until storage is full. Disabling durability features like fsync or full_page_writes can cause unrecoverable corruption after power loss or kernel crashes. Some WAL parameters apply on reload, while postmaster parameters require a full server restart that disconnects clients.
Related: How to optimize PostgreSQL performance \\
Related: How to tune shared_buffers in PostgreSQL
Steps to tune WAL settings in PostgreSQL:
- Connect to the PostgreSQL server using psql as a superuser.
$ sudo -iu postgres psql -c "SELECT current_database();" current_database ------------------ postgres (1 row)
- Show the PostgreSQL cluster data directory hosting the /pg_wal directory.
$ sudo -iu postgres psql -c "SHOW data_directory;" data_directory ----------------------------- /var/lib/postgresql/16/main (1 row)ALTER SYSTEM writes changes into /postgresql.auto.conf inside the data directory.
- Check free space on the filesystem that stores the data directory.
$ df -h /var/lib/postgresql/16/main Filesystem Size Used Avail Use% Mounted on overlay 1.8T 15G 1.7T 1% /
Raising max_wal_size, min_wal_size, or wal_keep_size increases worst-case WAL disk usage.
- Record current WAL and checkpoint settings with reload/restart requirements.
$ sudo -iu postgres psql -c "SELECT name, setting, unit, context, pending_restart FROM pg_settings WHERE name IN ( 'wal_level', 'synchronous_commit', 'fsync', 'full_page_writes', 'wal_compression', 'checkpoint_timeout', 'checkpoint_completion_target', 'max_wal_size', 'min_wal_size', 'wal_keep_size' ) ORDER BY name;" name | setting | unit | context | pending_restart ------------------------------+---------+------+------------+----------------- checkpoint_completion_target | 0.9 | | sighup | f checkpoint_timeout | 300 | s | sighup | f fsync | on | | sighup | f full_page_writes | on | | sighup | f max_wal_size | 1024 | MB | sighup | f min_wal_size | 80 | MB | sighup | f synchronous_commit | on | | user | f wal_compression | off | | superuser | f wal_keep_size | 0 | MB | sighup | f wal_level | replica | | postmaster | f (10 rows)context values of sighup apply on reload, and postmaster requires a restart.
- Confirm durability-critical WAL safety settings remain enabled.
$ sudo -iu postgres psql -c "SHOW fsync;" fsync ------- on (1 row) $ sudo -iu postgres psql -c "SHOW full_page_writes;" full_page_writes ------------------ on (1 row)
Disabling fsync or full_page_writes can cause unrecoverable data corruption after power loss or system crashes.
- Set wal_level based on replication and decoding requirements.
$ sudo -iu postgres psql -c "ALTER SYSTEM SET wal_level = 'replica';" ALTER SYSTEM
Use replica for physical replication and base backups via the replication protocol, and use logical only when logical decoding or logical replication is required.
- Tune WAL recycling and checkpoint cadence for write-heavy workloads.
$ sudo -iu postgres psql -c "ALTER SYSTEM SET max_wal_size = '2GB';" ALTER SYSTEM $ sudo -iu postgres psql -c "ALTER SYSTEM SET min_wal_size = '256MB';" ALTER SYSTEM $ sudo -iu postgres psql -c "ALTER SYSTEM SET checkpoint_timeout = '10min';" ALTER SYSTEM $ sudo -iu postgres psql -c "ALTER SYSTEM SET checkpoint_completion_target = 0.9;" ALTER SYSTEM
Higher max_wal_size reduces checkpoint frequency, and checkpoint_completion_target spreads checkpoint writes over more time.
- Enable WAL compression to reduce WAL volume from full-page writes.
$ sudo -iu postgres psql -c "ALTER SYSTEM SET wal_compression = 'on';" ALTER SYSTEM
wal_compression trades CPU for lower WAL write volume and can reduce replication bandwidth on write-heavy systems.
- Set the default commit durability mode for latency-sensitive workloads.
$ sudo -iu postgres psql -c "ALTER SYSTEM SET synchronous_commit = 'on';" ALTER SYSTEM
Values like local or off reduce commit latency but can lose recent transactions on a crash, while remote_write and remote_apply increase durability guarantees for synchronous replication.
- Reserve WAL for standby servers when streaming replication is used without replication slots.
$ sudo -iu postgres psql -c "ALTER SYSTEM SET wal_keep_size = '512MB';" ALTER SYSTEM
Large wal_keep_size values can retain significant WAL on disk and must fit within available storage.
- Reload the PostgreSQL configuration to apply sighup settings.
$ sudo -iu postgres psql -c "SELECT pg_reload_conf();" pg_reload_conf ---------------- t (1 row)
- Check for settings requiring a PostgreSQL restart.
$ sudo -iu postgres psql -c "SELECT name, setting, context, pending_restart FROM pg_settings WHERE pending_restart IS true ORDER BY name;" name | setting | context | pending_restart ------+---------+---------+----------------- (0 rows)Restart requirements remain until the server is restarted, even after configuration reloads.
- Exit the psql session.
postgres=# \q
- Restart the PostgreSQL service to apply postmaster settings.
$ sudo systemctl restart postgresql
A restart disconnects active sessions and can interrupt applications during the service stop/start window.
- Verify WAL-related settings and confirm no restart is pending.
$ sudo -iu postgres psql -c "SHOW max_wal_size;" max_wal_size -------------- 2GB (1 row) $ sudo -iu postgres psql -c "SHOW checkpoint_timeout;" checkpoint_timeout -------------------- 10min (1 row) $ sudo -iu postgres psql -c "SELECT count(*) AS pending_restart_settings FROM pg_settings WHERE pending_restart IS true;" pending_restart_settings -------------------------- 0 (1 row)
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
