pgconfigurator
pgconfigurator

max_wal_size

No restart — takes effect on reloadtuned by pgconfiguratordisk size (MB/GB)

Soft ceiling on WAL between automatic checkpoints — bigger means fewer checkpoints.

What pgconfigurator would set
32 GB · 8 vCPU · NVMe · OLTP
Computing…
Tune for your exact server → /tunecomputed in your browser · nothing uploaded

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_timeout elapses or WAL since the last checkpoint approaches max_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_size until 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 default checkpoint_completion_target = 0.9 so 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:

  1. Disk — more space used for WAL between checkpoints.
  2. 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

Paste a plan into the analyzer →

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.

Related parameters