Ожидания получения BufferPin включают в себя:
1) Конфликты BufferPin на репликах (recovery conflict). Процесс на реплике startup должен получить блокировку на буфер, чтобы проиграть (replay, apply, накатить журнальную запись) HOT cleanup блока, для этого startup должен дождаться pincount=0. Быстрая очистка (HOT cleanup) выполняется на мастере серверными процессами очень часто и процесс startup, если столкнется с блоком, закреплённым запросом на реплике, полностью приостановит накат и будет ждать снятия закреплений блока. Накатом занимается только один процесс startup и в один поток. Из-за частых ожиданий BufferPin отставание реплики растёт и кажется, что startup не справляется. Мониторинг таких ситуаций затруднён, так как в представлении pg_stat_database_conflicts отражаются только конфликты, которые привели к прерыванию запросов на реплике, то есть, когда startup приостанавливал работу более, чем на max_standby_streaming_delay (по умолчению, 30 секунд), а в pg_stat_activity поймать ожидание BufferPin, которое длится доли секунды, почти невозможно. Из-за таких конфликтов, компаниии выделяют одну реплику, которая не обслуживает запросы, чтобы она только синхронизировалась и не отставала от мастера. Например, OpenAI, помимо 50 реплик, обслуживающих запросы на чтение, использует реплику, не обслуживающую никакие запросы, чтобы можно было на неё быстро переключиться (упомянута в 6 пункте в статье)
2) конфликты с автовакуумом при заморозке страниц. Такие конфликты есть и на мастере и на реплике и начинаются через 100 миллионов транзакций (по умолчанию, до 18 версии PostgreSQL). При недолгих тестированиях приложений не отлавливаются, проблемы начинаются при эксплуатации. Это одна из причин, по которой нагрузочные тесты длятся долго. Зная, как работает PostgreSQL, можно использовать недолгие тесты и оптимизировать приложение и параметры экземпляра, используя результаты недолгих тестов для обратной связи при настройке.