Как реализовать балансировку нагрузки на кластер PostgreSQL, чтобы запросы на чтение поступали только на слейв?
А как? Ну вот прямым текстом: как это в принципе и в теории возможно сделать без участия приложения?

begin isolation level repeatable read ;
select ... from users;
-- а дальше-то что?
Окей, begin действительно можно отсрочить до прихода следующего запроса, но вот абсолютно никак не позже запроса select вы обязаны решить, отправлять эту транзакцию на реплику либо на мастер. Как вы это определите? С равной вероятностью следующей командой может быть commit, другой select или пишущий запрос. Вы это никак не можете узнать, но вам уже необходимо эту транзакцию отправить куда-то и получить результат. И ровно так же вы не можете отправить запрос сначала на реплику, а запись потом на мастере потому что у вас развалится снэпшот транзакции.

select * from calculate_user_rating(423);
А это читающий или пишущий запрос? Да этого сама база не знает! Хрен его разберёт, что этой pl/python хранимке на непонятном для базы языке вздумается делать.

Репликами должно уметь пользоваться само приложение. Кроме самого приложения больше никто не знает, допустимо ли запрос отправлять на реплики и если да, то на какие именно
Нашел в закладках такую статью, сам не пробовал - https://www.percona.com/blog/2019/10/31/postgresql...