Diagnostic Queries
Symptoms
A query on a hot-standby replica was cancelled because it conflicted with WAL replay (e.g. the primary vacuumed rows the query still needed). PostgreSQL raises SQLSTATE 40001 (serialization_failure) on the standby.
- Only occurs on read replicas running queries during recovery.
- A DETAIL explains the conflict (snapshot, lock, tablespace, etc.).
- Long-running reporting queries on replicas are the usual victims.
What the server log shows
ERROR: canceling statement due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.
Why PostgreSQL raises this — what the manual says
Section 26.4.2 Handling Query Conflicts:
“Once the delay specified by max_standby_archive_delay or max_standby_streaming_delay has been exceeded, conflicting queries will be canceled.”
WAL replay on a standby may remove row versions or take locks that an in-progress read query depends on. To keep replay moving, the standby cancels the conflicting query with 40001 (unless feedback/delays are configured to prevent the conflict).
Common causes
- Vacuum/cleanup on the primary removing rows a standby query needs.
- Long-running queries on the standby during heavy WAL replay.
- Locks taken by replayed DDL conflicting with reads.
Relevant GUC parameters
| Parameter | Default | Effect |
|---|---|---|
hot_standby_feedback |
off | Tells the primary to avoid removing rows the standby still needs. |
max_standby_streaming_delay |
30s | How long replay may wait for conflicting queries before cancelling them. |
How to fix it
- Enable
hot_standby_feedback = onso the primary retains needed rows. - Increase
max_standby_streaming_delayto give queries more grace. - Retry the query, or run heavy analytics against a dedicated replica.
Related & next steps
Reference: PostgreSQL 18 Section 27.4 “Hot Standby”.
Thanks — noted. This helps keep the database accurate.