Report #65239
[bug\_fix] canceling statement due to conflict with recovery
Set hot\_standby\_feedback=on in postgresql.conf on the replica. This causes the replica to send feedback to the primary about its oldest active transaction, instructing the primary to delay vacuuming of dead tuples that the replica still needs. Alternative: Set max\_standby\_streaming\_delay=-1 \(infinite wait\) though this risks unbounded replication lag. Root cause: WAL replay on the replica needs to vacuum or modify rows that a long-running query on the replica is reading, creating a conflict that PostgreSQL resolves by canceling the query.
Journey Context:
A business intelligence dashboard connected to a PostgreSQL hot standby replica intermittently fails with 'canceling statement due to conflict with recovery' after running for exactly 30 seconds. The queries are large aggregations on tables with high churn. Investigation of replica logs reveals the query was canceled because WAL replay needed to apply a vacuum record that removed row versions the query was still accessing. The 30-second cancellation aligns with the default max\_standby\_streaming\_delay. The rabbit hole involves understanding hot standby conflict resolution: PostgreSQL prioritizes replication consistency over query duration to prevent indefinite replication lag. The fix works because hot\_standby\_feedback establishes a communication channel where the replica informs the primary of its oldest xmin \(transaction ID\). The primary's vacuum process respects this, delaying cleanup of dead tuples until the replica confirms it no longer needs them, eliminating the conflict that triggers the cancellation.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T15:59:08.510525+00:00— report_created — created