/explain/autovacuum_freeze_max_age

autovacuum_freeze_max_age

Transaction ids are 32-bit and wrap. A row whose xmin falls more than 2^31 transactions behind the current xid would appear to be in the future, so Postgres must mark old rows frozen before that happens. autovacuum_freeze_max_age is the table age at which autovacuum stops being optional: a worker is launched even if the table is otherwise idle and autovacuum is switched off. It is a deadline, not a schedule. On a table that vacuums normally, vacuum_freeze_table_age escalation rides one of those runs and advances relfrozenxid first, so this deadline never arrives and the value it holds stops mattering. That is why the default is usually the right answer: raising it only shortens the margin before the 2^31 limit forces the cluster read-only.

DEMO — xid age over 365 d, toy tablesame chart system as the report
2,147,483,647 (wraparound)freeze_max_age = 200,000,000
day 090180270365
autovacuum_freeze_max_age200,000,000
default 200,000,000 · max 2,000,000,000
xid consumption40.00 M/day
transactions per day, 1 M → 400 M
AGGRESSIVE VACUUM EVERY
5.0 d
RUNS PER YEAR
73.0
MARGIN TO SHUTDOWN
48.7 d
SEE ALSO
aggressive vacuumvacuum_failsafe_agewraparound← back to start
Lowering it to freeze sooner is the classic trap: below the age the xmin horizon allows, the table can never get back under the limit and a forced vacuum starts every naptime, forever. vacuum_freeze_min_age is the eagerness knob.
autovacuum_freeze_max_age — robovac