The autovacuum_freeze_max_age reloption exists so that the DBA can optionally have antiwraparound autovacuums run against a table that requires more frequent antiwraparound autovacuums. This has problems because there are actually two types of VACUUM right now (aggressive and non-aggressive), which, strictly speaking, is an independent condition of antiwraparound-ness. There is a tacit assumption within autovacuum.c that all antiwraparound autovacuums are also aggressive, I think. But that just isn't true, which leads to clearly broken behavior when the autovacuum_freeze_max_age reloption is in use.
Note that the VacuumParams state that gets passed down to vacuum_set_xid_limits() does not include anything about the "reloption version" of autovacuum_freeze_max_age. So quite naturally vacuum_set_xid_limits() can only work off of the autovacuum_freeze_max_age GUC, even when the reloption happens to have been used over in autovacuum.c. In practice this means that we can easily see autovacuum spin uselessly when the reloption is in use -- it'll launch antiwraparound autovacuums that never advance relfrozenxid and so never address the relfrozenxid age issue from the point of view of autovacuum.c. There is no reason to think that the user will also (say) set the autovacuum_freeze_table_age reloption separately (not to be confused with the vacuum_freeze_table_age GUC!). We'll usually just work off the GUC (I mean why wouldn't we?). I don't see why vacuumlazy.c doesn't just force aggressive mode whenever it sees an antiwraparound autovacuum, no matter what. Recall the problem scenario that led to bugfix commit dd9ac7d5 -- that also could have been avoided by making sure that every antiwraparound autovacuum was aggressive (actually the original problem was that we'd suppress non-aggressive antiwraparound autovacuums as redundant). I only noticed this problem because I am in the process of writing a patch series that demotes vacuum_freeze_table_age to a mere compatibility option (and even gets rid of the whole concept of aggressive VACUUM). The whole way that vacuum_freeze_table_age and autovacuum_freeze_max_age are supposed to work together seems very confusing to me. I'm not surprised that this was overlooked for so long. -- Peter Geoghegan