Errore PostgreSQL: canceling statement due to conflict with recovery

FATAL:  terminating connection due to conflict with recovery
DETAIL:  User query might have needed to see row versions that must be removed.
HINT:  In a moment you should be able to reconnect to the database and repeat your command.

Questo errore esiste solo sui replica in hot standby. Il replica deve applicare il WAL dal primario per restare in sincronia; la tua query aveva bisogno di versioni di riga che il WAL in arrivo (tipicamente pulizia del vacuum) rimuove. Dopo aver stallato il replay per max_standby_streaming_delay, il replica ha scelto la replica invece della tua query e l'ha annullata.

Cosa significa questo errore

Il replica serve letture mentre riproduce continuamente il WAL del primario — due lavori che entrano in conflitto quando il replay vuole cambiare o rimuovere dati che una query in esecuzione può ancora vedere. PostgreSQL prima ritarda il replay per far finire la query (fino a max_standby_streaming_delay, default 30 s), poi annulla la query. È un compromesso deliberato tra freschezza del replica e sopravvivenza della query, e ogni manopola si limita a spostarsi lungo quell'asse.

Cause comuni

Come diagnosticarlo

-- Sul replica: contatori dei conflitti per tipo e database
SELECT * FROM pg_stat_database_conflicts;

confl_snapshot è il caso della pulizia del vacuum; confl_lock punta al DDL sul primario. Correla con quali carichi girano sul replica in quei momenti.

Come risolverlo

Scegli il compromesso esplicitamente:

🔍 Lettura correlata: VACUUM & bloat — hot_standby_feedback fa sì che le query del replica trattengano la pulizia esattamente come le transazioni lunghe locali.