hot_standby_feedback and the bloat it buys
Turning hot_standby_feedback on stopped a replica query being cancelled — and stopped VACUUM reclaiming anything on the primary. The same table went from 0 dead tuples to 200,000 (48.14% dead) with no other change.
Problem
What you're actually looking at
The symptom as it shows up on a real server.
hot_standby_feedback is usually adopted to stop replica queries being cancelled mid-flight. It does that by making the standby's oldest snapshot hold back the primary's xmin horizon, which means VACUUM on the primary can no longer remove rows those replica queries might still need. The setting is not a fix; it is a transfer of the cost from the replica to the primary, and the transfer is invisible until the primary's tables stop shrinking.
Meridian enabled hot_standby_feedback after analysts complained about cancelled queries. Weeks later a table on the primary is half dead tuples and autovacuum appears to be running normally.
In plain English
A replica runs queries against data the primary is still changing. If the primary cleans up an old row version while a replica query still needs it, the replica has to kill that query. hot_standby_feedback stops that by having the replica tell the primary which old rows it still needs, so the primary keeps them. The queries survive — but the primary is now holding on to dead rows for as long as the longest replica query runs, and that is where the disk goes. You have not removed the problem, you have chosen which server pays for it.
Full runbook for this incident
- The full identify checklist — the exact signals that tell you it's this incident
- Every diagnostic query; PostgreSQL 18 output is attached only to the steps we captured
- The resolution path and the pitfalls that make it worse
- Mitigation steps to stop it recurring, plus a verify-you're-done query
More in this category
Other WAL & replication runbooks
Neighbouring incidents that share the same diagnostic surface.
Connected
How this connects to the rest of the library
A live view of this page's real cross-references — what explains it, what fixes it, what to tune, and where to go next. Every link is an authored relationship, not a guess.
Fixes these errors