ArmorDB Logo
ArmorDB
Postgresql 18 Maintenance Time Observability
PostgreSQL 18 Maintenance Time Metrics: What pg_stat_all_tables Adds
Back to Blog
Tech-News & Trends
July 30, 2026
6 min read

PostgreSQL 18 Maintenance Time Metrics: What pg_stat_all_tables Adds

PostgreSQL 18 adds table-level vacuum and analyze time counters. Learn what the new pg_stat_all_tables metrics mean and how to use them in production.

AE
ArmorDB EngineeringArmorDB engineering
PostgreSQL 18ObservabilityAutovacuum

PostgreSQL 18 adds a small-looking observability change that is easy to miss: table statistics can now report how much time PostgreSQL has spent vacuuming and analyzing each table. For operators, that turns maintenance from a background behavior you infer from logs into a trend you can query beside dead tuples, analyze counts, and autovacuum activity.

The problem is not that PostgreSQL lacked maintenance tooling. It already had autovacuum, progress views, logs, and cumulative table counters. The gap was historical time. When a production table slowly becomes more expensive to clean, you often notice through symptoms first: rising I/O, longer write stalls, stale planner statistics, or a noisy autovacuum log. PostgreSQL 18's new table-level maintenance time counters make that drift easier to measure before it becomes an incident.

What changed in PostgreSQL 18

The PostgreSQL 18 release notes list new timing columns for pg_stat_all_tables and its related views. The columns are total_vacuum_time, total_autovacuum_time, total_analyze_time, and total_autoanalyze_time. The PostgreSQL 18 monitoring documentation describes them as cumulative milliseconds spent manually vacuuming, autovacuuming, manually analyzing, and autoanalyzing a table. The vacuum counters exclude VACUUM FULL, and the documented vacuum times include time spent sleeping because of cost-based delay.

That last detail matters. These are not pure CPU or storage-service timings. They represent elapsed maintenance time from PostgreSQL's perspective, including deliberate throttling. A table can therefore show a high autovacuum time because it is difficult to clean, because maintenance is being slowed by cost delay settings, or because both are true. The metric is most useful when read with the rest of the table statistics instead of treated as a standalone performance number.

New counterWhat it measuresHow to interpret it
total_vacuum_timeManual VACUUM time in milliseconds, excluding VACUUM FULLUseful when humans or scheduled jobs supplement autovacuum
total_autovacuum_timeAutovacuum worker time in millisecondsA good first signal for tables consuming background maintenance capacity
total_analyze_timeManual ANALYZE time in millisecondsUseful after bulk loads, migrations, and targeted statistics refreshes
total_autoanalyze_timeAutoanalyze worker time in millisecondsHelps identify tables whose planner statistics are costly to keep fresh

The feature fits with other recent PostgreSQL observability work: progress views show what is happening now, logs explain completed maintenance events if configured, and cumulative statistics show long-term behavior. PostgreSQL 18 closes a practical gap by making table-level maintenance cost queryable without log scraping.

Why managed PostgreSQL teams should care

Autovacuum is usually invisible until it is not. A write-heavy table can accumulate dead rows, delay page cleanup, and increase index bloat. A large append-mostly table can spend meaningful time in analyze without obvious application errors. Multi-tenant SaaS tables may hide one noisy tenant inside aggregate database-level graphs. When maintenance time is visible per table, the first question changes from "is autovacuum running?" to "which tables are spending our maintenance budget, and is that trend expected?"

For managed PostgreSQL users, this is especially useful because the operating model is shared between the provider and the application team. The provider can keep the service healthy, but only the application owner knows why a table suddenly changed write patterns, gained a large JSONB column, or started receiving bulk imports every hour. Table-level time counters give both sides a common vocabulary for support conversations and capacity decisions.

ArmorDB already recommends watching autovacuum and bloat as part of production readiness; this metric makes that guidance easier to operationalize. If you are reviewing a growing application, pair these counters with the bloat and write-pattern checks in our PostgreSQL autovacuum guide at /blog/postgresql-autovacuum-bloat-managed-databases.

A practical query to start with

After upgrading to PostgreSQL 18, begin with a simple ranking query. Use it as a trend baseline rather than a one-time verdict, because cumulative statistics become more useful after you collect snapshots over time.

SELECT
  schemaname,
  relname,
  n_live_tup,
  n_dead_tup,
  autovacuum_count,
  autoanalyze_count,
  total_autovacuum_time,
  total_autoanalyze_time
FROM pg_stat_all_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY total_autovacuum_time DESC
LIMIT 20;

Run the query after a normal traffic window, then compare it again after a day or a week. A table that ranks high once may simply have been cleaned after a migration. A table that keeps climbing faster than its peers deserves investigation, especially if dead tuples remain high or autovacuum counts are frequent.

A useful dashboard should show the counter deltas, not only the absolute cumulative values. Reset events, failovers, restores, and statistics resets can change the baseline, so store the time of each sample and annotate operational events. If your monitoring system can compute rates, graph autovacuum milliseconds per hour by table and compare it with writes, dead tuples, and relation size.

What to do when a table is expensive to maintain

The counter tells you where to look; it does not prescribe the fix. Start by confirming the workload. A high-update table with many dead tuples may need autovacuum settings tuned per table, shorter transactions, better batching, or fewer updates to indexed columns. A table with high analyze time may have grown large enough that default statistics work is no longer cheap, or it may have columns with skewed distributions that require targeted statistics decisions.

Look for blockers before changing knobs. Long-running transactions can prevent vacuum from removing dead tuples even when workers run regularly. Replication slots can retain WAL and make maintenance symptoms look like storage pressure. Heavy indexes increase cleanup work, so unused indexes on high-write tables deserve the same scrutiny as slow queries.

For tables with predictable bulk imports, it can be cleaner to schedule manual VACUUM or ANALYZE around the import rather than let autovacuum discover the work at an inconvenient time. For tables that are continuously hot, per-table autovacuum settings may be appropriate, but make changes gradually and watch I/O. PostgreSQL's documentation notes that routine vacuuming is necessary, and that autovacuum depends on the statistics collection facility; disabling or starving it usually turns a maintenance problem into a reliability problem.

How this changes upgrade planning

This is not a reason to rush a major upgrade by itself. It is a reason to update the observability checklist for PostgreSQL 18 test environments. Add the new columns to staging dashboards, run representative write and maintenance workloads, and decide which alert thresholds should be based on deltas rather than absolute values.

During an upgrade rehearsal, compare maintenance time before and after heavy migrations. If a schema change adds indexes to a busy table, the new counters can help verify whether autovacuum work increased in proportion to the write volume. If an application change reduces unnecessary updates, the same dashboard should show maintenance time flattening over the next sampling windows.

The biggest mistake is treating the new counters as a replacement for logs or progress views. They are better as a map. Use pg_stat_progress_vacuum or pg_stat_progress_analyze to inspect active work, logs to understand completed maintenance events in detail, and pg_stat_all_tables to see which tables are consuming maintenance time over the long run.

Takeaway

PostgreSQL 18's maintenance time counters are not flashy, but they are operationally valuable. They make it easier to see which tables require the most vacuum and analyze attention, which gives teams a better path from vague database load to specific remediation. For production systems, add these counters to your PostgreSQL 18 upgrade checklist, collect deltas over time, and investigate sustained outliers before they turn into bloat, stale plans, or noisy support escalations.

Sources and further reading

Topic

Tech-News & Trends

Updated

Jul 30, 2026

Read time

6 min read

About the author

ArmorDB Engineering writes about PostgreSQL operations, security, and infrastructure decisions for teams building production apps on ArmorDB.