Return transaction id and multixact wraparound headroom: age(datfrozenxid) and age(datminmxid) for every database, the oldest tables by age(relfrozenxid) including TOAST tables (often the relation actually holding the horizon back), each xid and multixact age as a percentage of…
read-onlyany connectionsweeps instancesweeps group
wraparoundStatus([limit], [schema])
Return transaction id and multixact wraparound headroom: age(datfrozenxid) and age(datminmxid) for every database, the oldest tables by age(relfrozenxid) including TOAST tables (often the relation actually holding the horizon back), each xid and multixact age as a percentage of the effective freeze_max_age and of the limit at which the cluster stops accepting write transactions, plus the per-table freeze storage parameters and last vacuum times.
That limit is 2144483647, not 2^31: PostgreSQL refuses new transaction ids three million short of wraparound, and warns in the log forty million short of it -- wraparound_warn_limit and xids_until_warn_limit carry the earlier one, which is the threshold an operator has usually already seen fire. Two alarms live in these numbers and only one is an emergency: past autovacuum_freeze_max_age PostgreSQL forces an anti-wraparound vacuum, which is loud maintenance working as designed, while approaching the wraparound limit ends in the server refusing writes -- xid_percent_of_freeze_max_age against xid_percent_of_wraparound_limit tells them apart and xids_until_wraparound_limit is the budget.
Recovery does NOT need single-user mode: the documentation says plainly that stopping the postmaster is neither necessary nor desirable, and the fix is a plain database-wide VACUUM in normal multi-user mode. Not VACUUM FULL, which needs an xid of its own and will fail; not VACUUM FREEZE, which does more than the minimum needed to restore service. Past vacuum_failsafe_age VACUUM takes extraordinary measures -- and it is any VACUUM, not only autovacuum: the cost-based delay stops being applied, non-essential work such as index vacuuming is bypassed, AND the Buffer Access Strategy is disabled so the vacuum is free to use all of shared_buffers.
That third effect is why the cache looks wrecked during one, which bufferCacheSummary will show and nothing else explains. Default 1.6 billion, silently raised to no less than 105% of autovacuum_freeze_max_age. Rank tables by relfrozenxid age rather than size, since the oldest object sets the horizon however small it is, and read toast_for -- a TOAST table is frequently the offender and carries nobody's name. If the age will not fall, vacuum is not the problem: nothing can be frozen past the oldest transaction still visible to something, so more workers and a manual VACUUM FREEZE achieve nothing while the horizon is held.
Four things hold it -- a replication slot (replicationSlots), a long-running transaction (currentActivity.backend_xmin), a standby with hot_standby_feedback, and a prepared transaction, which is invisible in pg_stat_activity and not read by this server: query pg_prepared_xacts directly when nothing else explains it.
Also accepts connection, instance, group, described once under arguments every tool takes.
Transaction id and multixact headroom. An absent extension or a missing grant is reported as {error, hint} instead.
| Field | Type |
|---|---|
| databases | object | null |
| limits | object | null |
| tables | array | null |
A physical replica is byte-identical here, so asking each member of a replication group adds nothing. Dead tuples and the last vacuum and analyze times describe work that only happens on a primary; on a replica they are noise, not a second opinion.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "wraparoundStatus",
"arguments": {
"limit": 1
}
}
}
{
"databases": {
"shop": {
"xid_age": 182004412,
"xid_percent_of_freeze_max_age": 91.0,
"xid_percent_of_wraparound_limit": 8.5,
"mxid_age": 1204,
"mxid_percent_of_freeze_max_age": 0.0
}
},
"limits": {
"autovacuum_freeze_max_age": 200000000,
"wraparound_limit": 2144483647,
"wraparound_warn_limit": 2104483647
},
"tables": [
{
"schema": "shop",
"name": "events_2025_09",
"kind": "table",
"toast_for": null,
"xid_age": 182004410,
"freeze_max_age": 200000000,
"size": 1182990336,
"last_autovacuum": "2026-06-01T04:12:00Z"
}
]
}
Invented values on a fictional shop database, shaped by and checked against this tool's output schema. Real output is returned as structuredContent to clients that negotiate MCP 2025-06-18 or later.
diskUsage, databaseSize, serverSettings, currentActivity, currentLocks, databaseStats, statementStats, progressStats, ioStats, checkpointStats, tableIOStats, hostCapacity, bufferCacheSummary, bufferCacheContents