El apunte de default_transaction_read_only es bueno, pero ojo: no todas las consultas que parecen de solo lectura lo son. Si usan funciones con side effects (como nextval() o algunas funciones volátiles), PostgreSQL lanzará un error en read-only. Y si tienen algún ORM que haga SELECT ... FOR UPDATE en algún flujo, también reventará. Dicho esto, para sesiones de reporting o dashboarding, es una medida excelente.
Otra cosa que no mencionaron y que a mí me ha salvado varias veces: configurar `lock_timeout` a nivel de sesión o de base de datos. NOWAIT lanza el error al instante, pero a veces quieres esperar un poco (p.ej., 2 segundos) antes de fallar, para no cascarear la app por un lock de 100ms. Con `SET lock_timeout = '2s'` evitas el deadlock sin sacrificar la disponibilidad. Eso, combinado con el `idle_in_transaction_session_timeout`, es mi receta estándar.
Y para el tema del ORM, si pueden, revisen si tienen alguna forma de habilitar el modo de autocommit por defecto. En Hibernate, por ejemplo, `hibernate.connection.autocommit = true` evita que las transacciones queden abiertas sin querer. No es la panacea, pero reduce la fricción.