PostgreSQL "canceling statement due to conflict with recovery" — Why Replicas Cancel Queries?
Why replica queries get cancelled due to recovery conflicts, diagnosis via pg_stat_database_conflicts, and three mitigation strategies.
Operational Verification & Reliability Metadata
The error string is a symptom, not the root cause. Do not restart the server blindly. Run the diagnostic queries below to pinpoint the actual failure mode.
▸Symptoms
ERROR: canceling statement due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.This error is encountered exclusively on standby replicas (hot standby). While a long-running SELECT query executes, incoming WAL records from the primary attempt to purge dead tuple versions read by that query. The replica must either delay WAL replay (inducing replication lag) or cancel the query. Default behavior cancels the query after waiting 30 seconds.
▸Root Cause Diagnostic Query
Execute on the replica:
SELECT datname,
confl_tablespace,
confl_lock,
confl_snapshot,
confl_bufferpin,
confl_deadlock
FROM pg_stat_database_conflicts
WHERE datname = current_database();- •
confl_snapshotclimbing → Tuple version conflict. - •
confl_lockclimbing → Exclusive table lock (ALTER TABLE/TRUNCATE) executed on primary. - •
confl_bufferpinclimbing → Long-held buffer pin contention.
▸Ordered Remediation Steps
- 1Enforce Statement Timeouts: Set predictable bounds (
SET statement_timeout = '120s';). - 2Increase Standby Delay: Increase
max_standby_streaming_delay = '300s'trading replication freshness for query stability. - 3Enable `hot_standby_feedback` cautiously: Prevents vacuum on primary for active standby transactions, but carries severe table bloat risks if analytical queries are unbounded.
- 4Isolate Workloads: Separate transactional read-replicas from heavy batch analytical reporting nodes.
Other Database Error Triage Playbooks
Other battle-tested diagnostic guides for high-severity database errors.
PostgreSQL too many clients already: 6-Step Resolution
Three root causes of FATAL: sorry, too many clients already, single diagnostic query to identify the cause, and permanent mitigation via max_connections and PgBouncer.
PostgreSQL password authentication failed: Root Cause and Fix
Four root causes of psql password authentication failed: incorrect password, md5/SCRAM mismatch, pg_hba.conf rule ordering, and port/cluster confusion. Step-by-step triage.
PostgreSQL connection refused: 8-Step Definitive Triage
Difference between connection refused, timeout, and no pg_hba entry; triage for listen_addresses, port conflicts, firewalls, and Docker container mappings.