PG.L7.TRACK_COUNTS_OFF — A server that stopped counting what autovacuum decides by
- Category: performance
- Level: 7
- Confidence: deterministic
- Downtime class: none — nothing here is a schema change
- Stability: stable
- Suites: audit
- Applies to: PostgreSQL 18
What it reports
A server that hands new connections track_counts = off. The setting decides whether the server counts row changes and scans, and those counts are what autovacuum decides by.
What it costs
Autovacuum stops without being off. Without the counts it has nothing to decide by, so it vacuums and analyzes no table on its own, even though autovacuum itself still reads on. That is PG.L7.AUTOVACUUM_OFF under another name, and one that passes the check everybody makes first.
Every index looks unused. The index scan counters stop as well. Measured on PostgreSQL 18: three index scans in a session with track_counts = off left pg_stat_user_indexes.idx_scan where it was. PG.L7.INDEX_UNUSED therefore answers undetermined on such a server instead of advising a drop.
The value it judges
The value a new connection gets, never the reading session's own. A superuser may switch track_counts off for one session, and that says nothing about the connections an application makes. A database default does count: measured on PostgreSQL 18, ALTER DATABASE … SET track_counts = off makes off what every new connection of that database gets.
Flagged
# postgresql.conf
track_counts = off
Preferred
# postgresql.conf
track_counts = on
The overhead it saves is small next to what it stops: it is on by default because autovacuum needs it.
Unreadable is not off
A role that may not read the setting gets undetermined with a named reason, never a pass.
Why there is no MySQL twin
InnoDB's purge runs whatever is configured, so the autovacuum half has no counterpart there. The index usage half does, in performance_schema, and the MySQL reader already treats a disabled performance schema as a usage reading it could not make.
Sources
- PostgreSQL 18: run-time statistics, the setting, on by default because the autovacuum daemon needs the counts
- PostgreSQL 18: automatic vacuuming, which states that
track_countsmust be on for autovacuum to work
The fix material this rule carries
A finding from this rule carries a payload whose strategy is none: this rule has looked,
and there is no safe standard sequence. That is a conclusion rather than an omission — a
finding with no payload at all says only that nobody wrote one.
The payload is material for you or an agent to apply. SQLens writes no migration and runs no DDL. See the remediation payload for every field, the placeholder semantics, and the version rules a consumer has to follow.