지난주 화요일 오후, 모니터링 알람이 울렸다. PgBouncer 앞단의 connection 사용량이 평소 대비 3배 가까이 튀어 있었고, 어플리케이션 쪽 P99 레이턴시는 슬슬 200ms를 넘기고 있었다. 트래픽은 평소 수준. 이상한 점은 RDS Postgres의 active connection 수가 거의 변동이 없다는 거였다. 즉, 클라이언트 → PgBouncer 사이에서 뭔가 막혀 있다는 뜻이다.이번 글은 그날 밤 새벽 2시까지 잡고 있던 이 문제를 어떻게 추적했는지, 그리고 결국 prepared statement와 transaction pooling이 충돌하던 지점을 어떻게 풀어냈는지에 대한 기록이다. 결론부터 말하면, 우리가 두 달 전에 한 PgBouncer 버전 업그레이드가 진짜 원인이었다.처음..