Scenario
A DBA notices that the buffers_maxwritten_clean counter in pg_stat_bgwriter is steadily rising. This counter increments every time the background writer stops a cleaning scan because it hit bgwriter_lru_maxpages. It means the bgwriter is being throttled — it cannot keep up with dirty buffer production, so checkpoints must clean buffers themselves, causing checkpoint I/O spikes. The root cause: bgwriter_lru_maxpages is set too low (default 100) for a write-heavy workload.
How to Identify
Conditions:
buffers_maxwritten_clean in pg_stat_bgwriter is non-zero and rising
- I/O spikes correlate with checkpoint timing (
buffers_checkpoint rises sharply)
bgwriter_lru_maxpages = 100 (default) — bgwriter stops after 100 pages per round
- Disk write latency increases during checkpoint periods
buffers_clean (written by bgwriter) is much lower than buffers_checkpoint
Analysis Steps
-- Check bgwriter statistics:
SELECT
buffers_checkpoint,
buffers_clean,
maxwritten_clean,
buffers_backend,
buffers_backend_fsync,
buffers_alloc,
stats_reset
FROM pg_stat_bgwriter;
-- buffers_checkpoint >> buffers_clean = bgwriter not keeping up
-- maxwritten_clean > 0 = bgwriter being throttled (hit lru_maxpages limit)
-- buffers_backend > 0 = backends writing their own buffers (bad — means shared_buffers pressure)
-- Check bgwriter settings:
SELECT name, setting, unit
FROM pg_settings
WHERE name LIKE 'bgwriter%'
ORDER BY name;
-- bgwriter_lru_maxpages = 100 (default) — increase if maxwritten_clean is rising
-- bgwriter_lru_multiplier = 2.0 (default) — multiplier for anticipated need
-- bgwriter_delay = 200ms (default) — sleep between bgwriter rounds
Pitfalls
buffers_maxwritten_clean rising is a symptom, not the root cause — the root cause is that the workload produces dirty buffers faster than bgwriter can flush them.
- Increasing
bgwriter_lru_maxpages increases bgwriter I/O — on already I/O-saturated systems this can make things worse. Tune in small increments.
buffers_backend > 0 means backends are writing their own buffers instead of finding clean ones — this blocks foreground queries. It indicates shared_buffers is too small or bgwriter is severely under-configured.
buffers_backend_fsync > 0 is critical: backends had to do their own fsync (data integrity path) — this means the checkpoint process was also overwhelmed.
pg_stat_bgwriter is cumulative since stats_reset. Always compare deltas over time, not absolute values.
Resolution Approach
Increase bgwriter_lru_maxpages to allow bgwriter to write more pages per round. Increase bgwriter_lru_multiplier slightly to scan more buffer candidates. Also check checkpoint_completion_target (should be 0.9) and max_wal_size to spread checkpoint I/O.