Cookbook recipe

Tables not being autovacuumed — finding the gaps

Applies to PostgreSQL 13–17 Last reviewed Nov 2025 Grounded in source
Estimated investigation4 min

Scenario

Some tables have accumulated significant dead tuples or stale statistics but autovacuum has not run on them — they may have been excluded, throttled out, or have per-table settings that prevent timely cleanup. Diagnose it --…

Investigation Path

Some tables have accumulated significant dead tuples or stale statistics but autovacuum has not run on them — they may have been excluded, throttled out, or have per-table settings that prevent timely cleanup.

Diagnose it

-- Tables with dead tuples but no recent autovacuum:
SELECT schemaname,
       relname,
       n_dead_tup,
       n_mod_since_analyze,
       n_ins_since_vacuum,
       last_autovacuum,
       last_autoanalyze,
       autovacuum_count,
       autoanalyze_count
FROM pg_stat_all_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
  AND (last_autovacuum IS NULL
       OR last_autovacuum  1000
ORDER BY n_dead_tup DESC
LIMIT 20;

Why it happens

Possible reasons autovacuum skips a table: (1) the table has autovacuum_enabled = false
set via storage parameters; (2) the table is too small to cross the threshold
(autovacuum_vacuum_threshold + scale_factor * n_live_tup); (3) all autovacuum
worker slots are busy with other tables; (4) the table belongs to a schema not visible
to autovacuum (extremely rare); (5) the cost-delay throttle is so aggressive that the worker
never finishes.

How to fix it

-- Check per-table settings:
SELECT relname, reloptions
FROM pg_class
WHERE relname = 'your_table_name';

-- Check if autovacuum is disabled:
SELECT relname, reloptions
FROM pg_class
WHERE reloptions::text LIKE '%autovacuum_enabled=false%';

-- Re-enable if needed:
ALTER TABLE tablename RESET (autovacuum_enabled);

Prevent it next time

Never set autovacuum_enabled = false on a user table in production unless you
have a fully managed VACUUM schedule replacing it. Monitor last_autovacuum across
all tables in a scheduled query; alert on any table that has not been vacuumed in 24 hours and
has more than a threshold of dead tuples.

This is a Pro lesson

Get every Learning Pathway and cookbook recipe — grounded in PostgreSQL source code, with diagnostics, fixes, and prevention for each topic.

Continue this lesson to learn:

  • Related & next steps
  • All 36 Learning Pathway lessons
  • 170+ cookbook recipes
  • Source-grounded diagnostics & fixes

Secure checkout Cancel anytime Source-grounded

Career Impact

This scenario builds production judgment and operational confidence under pressure.

Open Career Dashboard →

Keep going

Related & next steps

Was this helpful?

← All cookbook recipes