본문 바로가기
Q&A해결2026년 7월 16일1분 읽기

Prisma로 배포하니 Timed out fetching a new connection (P2024)가 터져요

p
prisma_dowon
조회 1251댓글 2

Next.js 앱을 Vercel에 올리고 DB는 RDS PostgreSQL 쓰고 있는데요, 로컬이랑 스테이징에선 멀쩡하다가 실서비스에서 사람 좀 몰리면 아래 에러가 간헐적으로 납니다.

PrismaClientKnownRequestError:
Timed out fetching a new connection from the connection pool.
(Current connection pool timeout: 10, connection limit: 17)

DB 쪽 max_connections는 넉넉히 잡아뒀다고 생각했는데도 이래요. 코드에선 PrismaClient를 매 라우트에서 new 하지는 않고 있고요(그래도 혹시 몰라 확인함). 커넥션 limit을 그냥 확 올려버리면 되나 싶다가도 뭔가 근본 원인이 따로 있는 것 같아서 여쭤봅니다. 왜 배포 환경에서만 이럴까요?

댓글 2

김김영삼3개월 전
이건 Prisma 풀 크기 문제라기보단 서버리스 구조랑 안 맞아서 생기는 전형적인 증상이에요. Vercel 같은 서버리스는 요청이 몰리면 함수 인스턴스를 여러 개(수십~수백 개) 동시에 띄우는데, 인스턴스마다 각자 PrismaClient를 들고 있고 각자 커넥션 풀(기본 17개 근처)을 엽니다. 그러니 실제 DB로 나가는 커넥션은 대략 동시 인스턴스 수 x 풀 크기가 돼서 RDS max_connections를 순식간에 넘겨요. 그러면 새 커넥션을 못 얻어서 P2024로 떨어지는 거고요.

limit을 올리면 오히려 악화됩니다. 반대로 가야 해요.

첫째, DB 앞에 커넥션 풀러를 두세요. RDS면 RDS Proxy, 아니면 PgBouncer를 transaction 모드로. 앱은 풀러 포트로 붙고, 실제 DB 커넥션은 풀러가 재사용해줍니다.

둘째, 서버리스에서는 DATABASE_URL에 connection_limit=1 을 붙여서 인스턴스당 1개만 쓰게 하세요. 인스턴스가 많아도 풀러가 뒤에서 몰아주니까요.

셋째, PgBouncer transaction 모드를 쓰면 prepared statement 충돌이 나니 URL에 pgbouncer=true 를 꼭 넣어야 합니다. 이거 빠뜨리면 또 다른 에러로 헤매요.

max_connections를 키우는 건 최후의 임시방편이고, 서버리스+Postgres는 풀러가 사실상 필수라고 보시면 됩니다.
pprisma_dowon(guest)3개월 전
RDS Proxy 붙이고 connection_limit=1 에 pgbouncer=true 까지 넣으니까 그 뒤로 P2024가 한 번도 안 났습니다. limit 올려서 막으려던 게 완전 헛다리였네요. 구조를 정확히 짚어주셔서 감사합니다.
Ctrl+Enter로 등록