BUG #19549: Physical replication slot xmin value stuck
The following bug has been logged on the website:
Bug reference: 19549
Logged by: nitin mangnale
Email address: nmangnale2@gmail.com
PostgreSQL version: Unsupported/Unknown
Operating system: Linux (ubuntu 22.04 LTS)
Description:
Hello PostgreSQL Community,
I am looking for assistance in investigating what appears to be an unusual
replication/xmin behavior on PostgreSQL 13.20.
Environment
- PostgreSQL Version: 13.20 (Community PostgreSQL)
- Replication Type: Physical Streaming Replication
- Primary Server: 1
- Standby Servers: 2
- Replication Slots: Physical replication slots
- One standby is used primarily as a reporting/read-only node.
- "hot_standby_feedback" is enabled.
Problem Description
One of our standby servers periodically causes a physical replication slot
on the primary to retain a very old "xmin". The "age(xmin)" continuously
increases over time, preventing vacuum from advancing normally on the
primary.
The unusual part is that we cannot identify any backend or query responsible
for holding the snapshot.
The issue only affects one standby. The second standby remains healthy.
Restarting the affected standby immediately clears the problem, but after
several days the same behavior returns.
Observed Behavior
On the primary:
SELECT now(),
slot_name,
slot_type,
active,
xmin,
age(xmin),
catalog_xmin,
restart_lsn
FROM pg_replication_slots
ORDER BY age(xmin) DESC NULLS LAST;
Example output:
slot_name : oseu2012766
slot_type : physical
active : true
xmin : 788928341
age(xmin) : 5419501 (continuously increasing)
restart_lsn : 1835DD/EB000000
The second standby slot behaves normally:
slot_name : oseu2012755
age(xmin) : ~6000
---
On the primary:
SELECT application_name,
backend_xmin,
age(backend_xmin),
state,
sync_state
FROM pg_stat_replication;
Output:
application_name | backend_xmin | state
-----------------+--------------+----------
walreceiver | NULL | streaming
walreceiver | NULL | streaming
"backend_xmin" is NULL for both standby connections.
---
On the affected standby:
We checked:
- pg_stat_activity
- long-running transactions
- idle in transaction sessions
- backend_xmin
- xact_start
No session appears to hold the reported xmin.
Example:
SELECT pid,
usename,
application_name,
backend_xmin,
age(backend_xmin),
state,
query
FROM pg_stat_activity
WHERE backend_xmin = 788928341;
Returns:
0 rows
We also reviewed all active sessions and found only short-running reporting
queries (generally under 20 seconds).
---
Replication Status
- Replication lag: None
- WAL receiver: Healthy
- WAL replay: Normal
- Physical replication slot remains active
---
Database Conflicts
SELECT *
FROM pg_stat_database_conflicts;
Output:
confl_snapshot = 0
confl_lock = 0
confl_deadlock = 0
confl_bufferpin = 20
---
Actions Already Performed
We have verified:
- No long-running queries
- No idle-in-transaction sessions
- No prepared transactions
- No replication lag
- No obvious replication slot issues
- No backend_xmin matching the slot xmin
- WAL receiver appears healthy
- Reporting queries are relatively short-lived
Restarting only the affected standby immediately releases the pinned xmin
and vacuum resumes normally.
However, after a few days, the same standby again begins holding an old
xmin.
The second standby does not exhibit this behavior.
Questions
1. Is this a known issue or edge case in PostgreSQL 13.20 involving physical
replication slots or hot_standby_feedback?
2. Is it expected for "pg_replication_slots.xmin" to remain pinned while
"pg_stat_replication.backend_xmin" is NULL?
3. Are there any known bugs in PostgreSQL 13.x related to stale standby
feedback or snapshot lifecycle that match this behavior?
4. Are there any additional internal views, debugging techniques, or GUC
parameters that would help identify the source of the pinned xmin?
5. Would upgrading to a newer PostgreSQL major version be expected to
resolve this behavior if it is related to snapshot or hot standby feedback
handling?
At this point we are considering rebuilding the affected standby, but we
would like to understand the root cause before doing so.
Any guidance would be greatly appreciated.
Thank you.
Hi,
On Thu, Jul 9, 2026 at 3:04 AM PG Bug reporting form
<noreply@postgresql.org> wrote:
The following bug has been logged on the website:
Bug reference: 19549
Logged by: nitin mangnale
Email address: nmangnale2@gmail.com
PostgreSQL version: Unsupported/Unknown
Operating system: Linux (ubuntu 22.04 LTS)
Description:Hello PostgreSQL Community,
I am looking for assistance in investigating what appears to be an unusual
replication/xmin behavior on PostgreSQL 13.20.
PostgreSQL 13 reached end of life in November 2025 [1]https://www.postgresql.org/support/versioning/. The community
no longer provides bug fixes or investigates issues for EOL versions,
so getting help here will be difficult. If possible, I would recommend
upgrading to a supported version and checking if the issue still
reproduces there.
[1]: https://www.postgresql.org/support/versioning/
Problem Description
One of our standby servers periodically causes a physical replication slot
on the primary to retain a very old "xmin". The "age(xmin)" continuously
increases over time, preventing vacuum from advancing normally on the
primary.The unusual part is that we cannot identify any backend or query responsible
for holding the snapshot.The issue only affects one standby. The second standby remains healthy.
Restarting the affected standby immediately clears the problem, but after
several days the same behavior returns.
Thanks for reporting this.
Observed Behavior
On the primary:
slot_name : oseu2012766
slot_type : physical
active : true
xmin : 788928341
age(xmin) : 5419501 (continuously increasing)
restart_lsn : 1835DD/EB000000
Did you check on the standby if there is any backend holding xmin =
788928341 or closer somewhere?
Questions
1. Is this a known issue or edge case in PostgreSQL 13.20 involving physical
replication slots or hot_standby_feedback?2. Is it expected for "pg_replication_slots.xmin" to remain pinned while
"pg_stat_replication.backend_xmin" is NULL?
Yes. Check the docs [2]https://www.postgresql.org/docs/devel/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-VIEW. The field backend_xmin shows the standby's
xmin horizon reported by hot_standby_feedback. This field will be null
if a replication slot is used (in that case, the standby's xmin is
shown in pg_replication_slots). So in your case, this is expected.
[2]: https://www.postgresql.org/docs/devel/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-VIEW
3. Are there any known bugs in PostgreSQL 13.x related to stale standby
feedback or snapshot lifecycle that match this behavior?
Without a reproducer or additional details or extensive checks on the
standby, it is hard to treat this as a bug.
4. Are there any additional internal views, debugging techniques, or GUC
parameters that would help identify the source of the pinned xmin?
Maybe it is worth looking at what the standby reports as xmins via
hot_standby_feedback [3]https://github.com/postgres/postgres/blob/REL_13_STABLE/src/backend/replication/walreceiver.c#L1252 and whether it matches what is being reported
in the primary's pg_replication_slots.xmin.
[3]: https://github.com/postgres/postgres/blob/REL_13_STABLE/src/backend/replication/walreceiver.c#L1252
5. Would upgrading to a newer PostgreSQL major version be expected to
resolve this behavior if it is related to snapshot or hot standby feedback
handling?
Without understanding the issue and query patterns on the standby, it
is hard to say. However, since PostgreSQL 13 is no longer supported by
the community, upgrading to a newer version in a sandboxed environment
and testing whether the issue recurs would be a reasonable next step.
At this point we are considering rebuilding the affected standby, but we
would like to understand the root cause before doing so.
Why do you think rebuilding the standby would resolve the issue?
--
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com