eduardweb.
PostgreSQLAvansat#devops#prisma#postgresql#database#pgbouncer

De ce îți crapă Prisma în producție cu PgBouncer și cum configurezi corect pool-urile

De Alexandru Matei, 14 iul. 2026 · 17 vizualizări · 2 like-uri

Postat 14 iul. 2026
typescript
datasource db {
  provider  = "postgresql"
  // Conexiunea prin PgBouncer pe portul 6432
  url       = env("DATABASE_URL") 
  // Conexiunea directă la Postgres pe portul 5432 pentru migrații
  directUrl = env("DIRECT_DATABASE_URL") 
}

Dacă folosești Prisma cu PostgreSQL în producție, probabil ai observat deja că ORM-ul ăsta mănâncă conexiuni pe pâine. Fără un pooler precum PgBouncer în fața bazei de date, la primul spike de trafic te trezești cu eroarea fatală "Too many clients". Dar dacă îl configurezi greșit, riști să-ți strici tranzacțiile sau să corupi sesiunile utilizatorilor.

Am pățit asta acum doi ani pe un proiect cu vreo 8.000 de utilizatori concurenți. Serverul de Postgres dădea semne de oboseală, iar procesorul stătea la 90% doar din cauza handshake-urilor TCP și a proceselor backend pe care Postgres le pornește pentru fiecare conexiune nouă. Am rezolvat problema adăugând PgBouncer, dar m-am lovit de toate bubele posibile până am nimerit setup-ul stabil.

Session vs Transaction Mode: Unde e capcana?

Implicit, multă lume lasă PgBouncer în session mode. În modul ăsta, când aplicația ta cere o conexiune, PgBouncer i-o alocă și o ține blocată până când aplicația o închide explicit. Pentru Prisma, asta e aproape inutil. ORM-ul va menține conexiunile deschise în pool-ul său intern, deci tot vei atinge rapid limita bazei de date.

Magia adevărată se întâmplă în transaction mode. Aici, o conexiune fizică la baza de date este returnată în pool-ul PgBouncer imediat ce s-a terminat tranzacția curentă. O singură conexiune la Postgres poate deservi zeci de request-uri HTTP aproape simultan. Am reușit să scădem numărul de conexiuni active pe Postgres de la 300 la doar 15, fără nicio degradare a performanței.

Dar avem un trade-off major de care trebuie să fii conștient. În transaction mode, nu poți folosi caracteristici care depind de starea sesiunii:

  • Tabele temporare (TEMP TABLE)
  • Comanda LISTEN/NOTIFY pentru evenimente în timp real
  • Prepared statements (decât dacă folosești PgBouncer v1.21+ care știe să facă track la ele la nivel de protocol)

Cum împaci Prisma cu PgBouncer

Prisma are nevoie de un workaround fiindcă folosește intens prepared statements. Când configurezi conexiunea, trebuie să adaugi parametrul ?pgbouncer=true în string-ul de conexiune. Acest parametru îi spune motorului Prisma să folosească o metodă alternativă de query, evitând prepared statements care ar zăpăci PgBouncer în mod tranzacție.

Mai mult, pentru migrații (prisma migrate), ai nevoie de o conexiune directă, fără PgBouncer, sau cel puțin de una configurată în session mode. Migrațiile rulează tranzacții complexe de DDL (Data Definition Language) și adesea blochează tabele sau folosesc lock-uri la nivel de sesiune.

Cum calculezi Pool Size în producție?

O greșeală comună pe care am văzut-o e să pui default_pool_size = 100 în PgBouncer și să lași Prisma cu setările implicite.

Fiecare conexiune activă în Postgres consumă în jur de 10-15 MB de memorie RAM pe server. Dacă ai un server cu 8GB RAM, nu vrei mai mult de 100-150 de conexiuni reale la Postgres. Formula care a funcționat cel mai bine pentru noi:

  1. În pgbouncer.ini, setează default_pool_size = 40 (limita de conexiuni fizice deschise către Postgres).
  2. Setează max_client_conn = 2000 (numărul de conexiuni pe care aplicația ta le poate deschide către PgBouncer).
  3. În string-ul de conexiune din aplicație (Prisma), limitează pool-ul intern cu connection_limit=5. Dacă ai 10 instanțe de microservicii sau containere serverless, 10 * 5 = 50 de conexiuni virtuale, pe care PgBouncer le va multiplexa perfect în cele 40 de conexiuni reale.

Voi cum gestionați conexiunile când scalați? Mergeți pe PgBouncer clasic sau ați trecut deja pe alternative cloud-native gen RDS Proxy ori Supabase Supavisor?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.