Hi, On Tue, Oct 6, 2026 at 4:49 AM Nisha Moond <[email protected]> wrote: > > 1) I observed an issue: > With v15, an aged failover slot also gets the standby's physical slot > invalidated on the primary. This behavior was also mentioned > upthread[1]. > > The standby forwards the synced copy's catalog_xmin through > hot_standby_feedback, so the physical slot carries a catalog_xmin ≤ > the failover slot's. The primary's checkpoint then invalidates both in > the same pass. > > IMO, the impact seems high for the cause: > - the standby loses streaming and WAL retention, and needs manual > action; it may even need a rebuild once the WAL is gone > - with the slot in synchronized_standby_slots, other failover slots > on the primary would also stall > - for synced slots it gains nothing: the failover slot is invalidated > anyway, and the next sync would release the catalog_xmin > Given the impact, I feel this should be handled.
Nice catch! I agree with your analysis. > IIUC, the same would also happen for a lagging or abandoned logical > slot owned by the standby. > > The difficulty I see is that the primary sees only one catalog_xmin > per physical slot. It can't tell whether the value comes from a synced > copy that will resolve itself, or from a lagging or abandoned slot > owned by the standby, which shouldn't be allowed to pin the primary's > catalog horizon indefinitely. Yes, AFAICS it happens for both: logical slots doing logical decoding on the standby, and slots being synced from the primary. > But it may not need to tell. Instead of invalidating the physical > slot, the primary could ignore an aged catalog_xmin in the feedback > and clear one already stored, so the slot stays valid. Yes, ignoring the received catalog_xmin from HS feedback seems correct to me. Unless I'm missing something, instead of clearing it the primary can store it up to the limit XID (next XID - XID age), which is newer than the received value. Also, I think we should emit a LOG message when this adjustment is made, for observability. > Vacuum can then > remove those catalog rows, and the standby's existing > recovery-conflict handling invalidates the slots that needed them as > "rows_removed". Those rows are lost with the current behaviour too, > once the physical slot is invalidated; this way the standby just stays > connected. > > The downsides I see: hot_standby_feedback's protection becomes bounded > by the primary's max_slot_xid_age, but that's no different from now, > where the standby loses its connection at the same bound. Also, the > slots on the standby show "rows_removed" as the invalidation reason, > though the underlying cause was the catalog_xmin age on the primary. > > Thoughts? I agree with your approach. With this, a physical slot never gets invalidated for an aged catalog_xmin. The checkpointer also moves the slot's catalog_xmin up to the limit XID when the standby is gone or no HS feedback is received any more. Vacuum then removes the older catalog rows, and the slots on the standby that needed them get invalidated as rows_removed once the standby replays those records. -- Bharath Rupireddy Amazon Web Services: https://aws.amazon.com
