max_wal_size
Soft ceiling on WAL between automatic checkpoints — bigger means fewer checkpoints.
What it does
max_wal_size is a soft limit on how much WAL accumulates before PostgreSQL triggers a checkpoint. Larger values let more WAL build up between checkpoints, which spreads out and reduces checkpoint I/O — a big win for write-heavy workloads — at the cost of more disk for WAL and potentially longer crash recovery.
How to tune it
If logs show frequent 'checkpoints are occurring too frequently' (or log_checkpoints reveals short intervals), raise it. Several GB is common on busy systems. Pair it with checkpoint_timeout and checkpoint_completion_target. It takes effect on reload — no restart needed.
In depth
What it really controls
max_wal_size is a soft limit on how much write-ahead log accumulates before
PostgreSQL forces a checkpoint. Together with checkpoint_timeout, it decides
how often checkpoints happen:
- A checkpoint fires when either
checkpoint_timeoutelapses or WAL since the last checkpoint approachesmax_wal_size— whichever comes first.
If max_wal_size is too small for your write rate, checkpoints are triggered by
WAL volume long before the timeout, so they happen constantly. Each checkpoint
re-flushes dirty pages, so frequent checkpoints mean repeatedly writing the same
hot pages — wasted I/O.
The symptom
This message in the log is the classic tell:
LOG: checkpoints are occurring too frequently (9 seconds apart)
HINT: Consider increasing the configuration parameter "max_wal_size".
Turning on log_checkpoints (default on in modern versions) lets you see the
interval and how many buffers each checkpoint wrote.
Tuning it
- Raise
max_wal_sizeuntil checkpoints are paced by time (checkpoint_timeout) rather than by filling the WAL budget. Several GB is common on busy systems. - Pair it with a longer
checkpoint_timeout(e.g. 15–30 min) and the defaultcheckpoint_completion_target = 0.9so the writes spread smoothly. - It applies on reload — no restart.
The trade-offs (not durability)
Raising max_wal_size does not risk losing committed data. What you trade is:
- Disk — more space used for WAL between checkpoints.
- Crash recovery time — more WAL to replay after an unclean shutdown.
For most write-heavy systems that trade is well worth the smoother, cheaper steady-state I/O.
What the analyzer flags
- Cold plan — heavy I/O; checkpoint storms can compound it
FAQ
- Does raising max_wal_size risk data loss?
- No — it only changes how often checkpoints happen, not durability. The trade-offs are more disk used for WAL and a potentially longer crash-recovery replay, not lost commits.
- Why am I getting 'checkpoints occurring too frequently'?
- WAL is hitting max_wal_size before checkpoint_timeout elapses, forcing early checkpoints. Raise max_wal_size (and review checkpoint_timeout) so checkpoints are paced by time, not by filling the WAL budget.