last_vacuum
Last vacuum timeInterface Metrics (5)
About this metric
The last_vacuum metric tracks the timestamp of the most recent vacuum operation performed on PostgreSQL tables, whether triggered manually or by the autovacuum daemon. VACUUM is a critical PostgreSQL maintenance operation that reclaims storage occupied by dead tuples (obsolete row versions created by UPDATE and DELETE operations), prevents transaction ID wraparound issues, and updates table statistics for the query planner. This metric provides operational visibility into whether tables are receiving necessary maintenance, as PostgreSQL's MVCC (Multi-Version Concurrency Control) architecture continuously generates dead tuples during normal operations that must be cleaned up to maintain database health.
From an operational and reliability perspective, monitoring last_vacuum is essential for preventing several critical failure modes. Tables that haven't been vacuumed recently may experience table bloat (excessive disk usage), degraded query performance due to scanning unnecessary dead tuples, and in extreme cases, transaction ID wraparound which can force PostgreSQL into emergency shutdown mode. Healthy patterns typically show vacuum operations occurring within hours to days depending on table update frequency and autovacuum configuration. High-traffic tables with frequent UPDATEs or DELETEs should show recent vacuum timestamps (within hours), while read-mostly tables may show longer intervals without concern.
Common alerting use cases include triggering warnings when tables exceed organization-defined thresholds (e.g., no vacuum in 7+ days for active tables, or 30+ days for any table), which may indicate autovacuum isn't keeping pace with write workload or has been improperly disabled. Troubleshooting scenarios often involve correlating stale last_vacuum timestamps with performance degradation, investigating whether autovacuum is blocked by long-running transactions (visible in pg_stat_activity), or determining if autovacuum settings like autovacuum_vacuum_scale_factor need tuning. This metric is particularly valuable for cost management as table bloat from inadequate vacuuming directly translates to wasted storage costs and can necessitate expensive VACUUM FULL operations that require exclusive table locks.
Available Content
The last_vacuum metric is your early warning system for some of PostgreSQL's most insidious performance issues—from bloat accumulation to the dreaded transaction ID wraparound. While many teams only think about vacuum when things go wrong, the real experts know that understanding when and why tables were last vacuumed reveals critical patterns about database health, autovacuum effectiveness, and potential resource bottlenecks before they impact users.
Our curated knowledge base brings together authoritative guidance from PostgreSQL core documentation, battle-tested troubleshooting strategies from teams running Postgres at scale, and workload-aware tuning recommendations that go far beyond default settings. Whether you're debugging why autovacuum isn't keeping up, trying to prevent transaction ID exhaustion, or optimizing vacuum schedules for your specific workload patterns, we've assembled the essential resources that SREs and database engineers rely on to keep PostgreSQL running smoothly. Discover how to interpret vacuum timing data, tune autovacuum parameters with confidence, and recognize the warning signs that warrant immediate attention.
Knowledge Base (9 documents, 1 chunks)
Technical Annotations (24)
Configuration Parameters (6)
autovacuum_vacuum_scale_factorrecommended: 0.01-0.05autovacuum_vacuum_thresholdrecommended: 50autovacuum_naptimeautovacuum_max_workersautovacuum_vacuum_cost_limitrecommended: 1000autovacuum_vacuum_cost_delayrecommended: 2CLI Commands (9)
SELECT schemaname, relname AS table_name, n_live_tup AS live_tuples, n_dead_tup AS dead_tuples, ROUND(n_dead_tup::numeric / NULLIF(n_live_tup, 0) * 100, 2) AS dead_pct, last_autovacuum, last_autoanalyze, autovacuum_count, autoanalyze_count FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 20;diagnosticALTER TABLE events SET (autovacuum_vacuum_threshold = 1000, autovacuum_vacuum_scale_factor = 0.005, autovacuum_analyze_threshold = 500, autovacuum_analyze_scale_factor = 0.005, autovacuum_vacuum_cost_delay = 0, autovacuum_vacuum_cost_limit = 3000);remediationVACUUMremediationANALYZEremediationSELECT schemaname, relname AS table_name, n_dead_tup AS dead_tuples, n_live_tup AS live_tuples, last_autovacuum, last_autoanalyze, CASE WHEN n_live_tup > 0 THEN round(100.0 * n_dead_tup / n_live_tup, 1) ELSE 0 END AS dead_tuple_ratio FROM pg_stat_user_tables WHERE n_dead_tup > 500 ORDER BY n_dead_tup DESC LIMIT 15;diagnosticALTER TABLE sim_events SET (autovacuum_vacuum_scale_factor = 0.02, autovacuum_vacuum_threshold = 500, autovacuum_vacuum_cost_delay = 2, autovacuum_vacuum_cost_limit = 1000);remediationSELECT relname, reloptions FROM pg_class WHERE relname = 'sim_events';diagnosticSELECT relname, reloptions FROM pg_class WHERE reloptions IS NOT NULL AND relkind = 'r';diagnosticgcloud sql instances patch MY_INSTANCE --database-flags=autovacuum_max_workers=6,autovacuum_vacuum_scale_factor=0.02,autovacuum_analyze_scale_factor=0.01,autovacuum_vacuum_cost_limit=2000,autovacuum_vacuum_cost_delay=0,autovacuum_naptime=15remediationTechnical References (9)
pg_stat_user_tablescomponentMVCCconceptdead tuplesconceptautovacuumcomponenttable bloatconceptHOT updatesconceptXID wraparoundconceptpg_classcomponentCloud SQL database flagscomponent