Error de 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.

Este error existe solo en réplicas hot standby. La réplica debe aplicar el WAL del primario para mantenerse sincronizada; tu consulta necesitaba versiones de fila que el WAL entrante (típicamente la limpieza del vacuum) elimina. Tras estancar el replay durante max_standby_streaming_delay, la réplica eligió la replicación por encima de tu consulta y la canceló.

Qué significa este error

La réplica sirve lecturas mientras reproduce continuamente el WAL del primario — dos trabajos que entran en conflicto cuando el replay quiere cambiar o eliminar datos que una consulta en marcha aún puede ver. PostgreSQL primero retrasa el replay para dejar terminar la consulta (hasta max_standby_streaming_delay, por defecto 30 s), y luego cancela la consulta. Es un compromiso deliberado entre la frescura de la réplica y la supervivencia de la consulta, y cada perilla solo se mueve a lo largo de ese eje.

Causas comunes

Cómo diagnosticarlo

-- En la réplica: contadores de conflictos por tipo y base de datos
SELECT * FROM pg_stat_database_conflicts;

confl_snapshot es el caso de la limpieza del vacuum; confl_lock apunta a DDL en el primario. Correlaciónalo con qué cargas de trabajo se ejecutan en la réplica en esos momentos.

Cómo solucionarlo

Elige el compromiso explícitamente:

🔍 Lectura relacionada: VACUUM & bloat — hot_standby_feedback hace que las consultas de la réplica retengan la limpieza exactamente como las transacciones locales largas.