El orden físico del heap es un factor que mucha gente pasa por alto. El seq scan itera en orden físico, que puede variar entre sesiones si hay actualizaciones o eliminaciones recientes (HOT updates, dead tuples, etc.). Al forzar el índice, el orden lógico es estable, lo que reduce la probabilidad de deadlock por adquisición cíclica de locks. Pero cuidado: si la tabla crece y el índice se vuelve menos selectivo, el planner podría volver al seq scan. Monitorea el plan en producción.
Otra opción que no mencionaron es usar SELECT ... FOR UPDATE SKIP LOCKED si tu lógica de negocio lo permite. Evita el bloqueo por completo, pero cambia la semántica (te saltas filas que están bloqueadas). Si el deadlock es raro, el reintento es aceptable, pero asegúrate de que la transacción sea idempotente.
También revisa si estás usando REPEATABLE READ o SERIALIZABLE. Con SERIALIZABLE, PostgreSQL puede lanzar errores de serialización (40001) que son más fáciles de manejar que un deadlock, porque son detectables de inmediato. Puedes configurar el driver para reintentar en ese caso.