Przejdź do treści
Wszystkie notatki

Supabase + Prisma: pooler vs direct URL

Dlaczego potrzebujesz obu i kiedy którego używać.

Opublikowano
Czas czytania
1 min
Tagi
#prisma · #supabase · #postgres

§ Treść

Jeśli kiedyś trafiłeś na błąd prepared statement "s0" already exists albo na timeout w Vercelu przy prisma.user.findMany(), problem prawie zawsze jest ten sam: używasz złego URL-a.

TL;DR

# .env.local
DATABASE_URL="postgresql://...pooler.supabase.com:6543/postgres?pgbouncer=true"
DIRECT_URL="postgresql://...db.supabase.co:5432/postgres"
// schema.prisma
datasource db {
  provider  = "postgresql"
  url       = env("DATABASE_URL")   // do queries (transakcje krótkie)
  directUrl = env("DIRECT_URL")     // do migracji (transakcje długie)
}

Dlaczego dwa URL-e

DATABASE_URL przechodzi przez pgBouncer w trybie transaction. Supabase ustawia to domyślnie. Dzięki temu możesz mieć 100 instancji serverless funkcji i każda dostaje połączenie z puli, zamiast otwierać 100 równoległych klientów do Postgresa.

Minus: nie wspiera prepared statements przy reużyciu. Prisma tego standardowo używa. Dlatego w URL-u dopisujesz ?pgbouncer=true — Prisma wtedy rozpoznaje, że nie może na nich polegać.

DIRECT_URL to bezpośrednie połączenie do bazy. Używane przez prisma migrate, bo migracje to długie transakcje DDL (CREATE TABLE, ALTER COLUMN), których pooler by nie przepuścił.

Typowe błędy

1. Brak ?pgbouncer=true

Objaw: losowe prepared statement "s0" already exists w produkcji, na lokalu wszystko działa.

2. Ten sam URL w obu polach

Objaw: prisma migrate dev wisi w nieskończoność albo timeout po 2 min.

3. DIRECT_URL w produkcji bez potrzeby

Jeśli nie odpalasz migracji z produkcji — nie potrzebujesz tam DIRECT_URL w ogóle. Ustaw go tylko w CI i lokalnie.

Sanity check

// Quick runtime check
await prisma.$queryRaw`SELECT current_setting('application_name')`;
// pooler connections pokazują np. "PostgREST/12"
// direct — nic albo nazwę Twojej apki

Tyle. Wraca się do tej pułapki co projekt, więc teraz mam notatkę.

Więcej notatek w indeksie. RSS pod /feed.xml.

Wszystkie notatki