postgresqlpgbouncerprisma
pgbouncer 앞에서 Prisma가 이상해지는 이유
✨ AI 요약
긴 글, 핵심만 먼저 — 이 글을 3줄로 정리해드려요.
조회 25
서버리스에서 Postgres를 쓰면 커넥션 풀러(pgbouncer)가 사실상 필수다. 그런데 풀러를 끼우는 순간 잘 되던 것들이 조용히 이상해진다. 원리를 알면 전부 설명되는 현상들이다.
왜 풀러가 필요한가
Postgres 커넥션은 비싸다(프로세스 하나씩). 서버리스는 인스턴스가 수십 개로 늘어날 수 있고, 각자 커넥션을 잡으면 max_connections(보통 100)가 순식간에 마른다. pgbouncer는 클라이언트 커넥션 수천 개를 실제 DB 커넥션 몇십 개로 다중화해 준다.
transaction 모드의 대가
pgbouncer의 핵심 설정이 pool_mode다. 서버리스에선 대부분 transaction 모드를 쓰는데, 이는 "트랜잭션 하나 끝날 때마다 커넥션을 다른 클라이언트에게 재배정"한다는 뜻이다. 그래서:
- prepared statement가 깨진다 — 내가 준비한 문장이 남의 커넥션에 가 있다. Prisma가 URL에
pgbouncer=true를 요구하는 이유 (prepared statement를 끈다) - 세션 상태가 증발한다 — SET, advisory lock, 임시 테이블처럼 커넥션에 붙는 것들은 전부 신뢰 불가
- LISTEN/NOTIFY 불가 — 커넥션을 계속 갈아타니까
# Prisma + pgbouncer 연결 문자열
postgresql://user:pw@pooler-host:6543/db?pgbouncer=true&connection_limit=5
connection_limit은 왜 낮게?
Prisma는 기본적으로 CPU 수 기반으로 풀을 잡는데, 서버리스 인스턴스가 N개면 총 커넥션은 N × limit이 된다. 풀러가 받아주는 클라이언트 수에도 한계가 있으니 인스턴스당 3~5로 낮게 잡는 게 안전하다.
마이그레이션은 직결로
DDL이나 마이그레이션은 세션 의존이 있어서 풀러를 거치면 안 된다. 그래서 directUrl(5432 직결)을 따로 두는 게 정석이다. 풀러 주소로 migrate를 돌리다 만나는 기괴한 에러의 90%가 이거다.
정리: 풀러는 "커넥션을 아껴 쓰는 대신 커넥션의 개인화를 포기"하는 거래다. 세션에 기대는 기능을 쓰고 있진 않은지만 점검하면 나머지는 공짜 확장성이다.