← Docs
Recipe

Postgres VACUUM + AUTOVACUUM tuning

Prevent transaction ID wraparound and reclaim dead tuples before they tank query performance.

Why this matters

Postgres uses MVCC — updates and deletes leave dead tuples behind. Without regular VACUUM, tables bloat, indexes fragment, and the transaction ID counter risks wraparound (which forces a shutdown).

Quick diagnostic

SELECT relname, n_dead_tup, last_vacuum, last_autovacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC;

Tuning parameters

  • autovacuum_vacuum_scale_factor→ 0.01 (trigger sooner on large tables)
  • autovacuum_vacuum_cost_limit→ 2000 (less throttling)
  • autovacuum_max_workers→ 4 (parallel workers)
  • autovacuum_naptime→ 15s (check more often)

Per-table overrides

ALTER TABLE orders SET (
  autovacuum_vacuum_scale_factor = 0.005,
  autovacuum_vacuum_cost_limit = 4000
);

Manual VACUUM

VACUUM (VERBOSE, ANALYZE) orders;

Use VACUUM FULL only during maintenance windows — it rewrites the entire table and takes an ACCESS EXCLUSIVE lock.

Monitoring

Watch pg_stat_progress_vacuum for running vacuums. Alert if any table exceeds 200M dead tuples or if age(datfrozenxid) approaches 1.5 billion.