Fait partie de Postgres géréPostgres · Prisma

Prisma P2024 : « Timed out fetching a new connection from the connection pool ».

P2024 veut dire qu’une requête a attendu une connexion du bassin plus longtemps que le délai de Prisma (10 secondes par défaut). Postgres ne vous a pas refusé : trop de requêtes roulaient en même temps, ou des requêtes lentes occupaient les connexions. Gardez un seul PrismaClient, dimensionnez le bassin selon la base et corrigez les requêtes lentes.

Faits vérifiés le

Lire les deux chiffres du message

Voici l’erreur complète de Prisma 6 et des versions antérieures :

  • connection limit est la taille du bassin de ce client. Si vous ne l’avez jamais fixée, Prisma 6 prenait cœurs physiques × 2 + 1. Le 9 ci-dessus, c’est une machine à 4 cœurs.
  • connection pool timeout est le temps, en secondes, qu’une requête attend dans la file de Prisma avant d’échouer avec P2024. Par défaut : 10.
Timed out fetching a new connection from the connection pool.
(Current connection pool timeout: 10, connection limit: 9)

Les causes habituelles, de la plus fréquente à la moins fréquente

  • Plusieurs instances de PrismaClient. Chaque new PrismaClient() a son propre bassin. Un client créé à chaque requête, dans chaque module ou à chaque rechargement à chaud de next dev multiplie les connexions jusqu’à épuiser la base ou le bassin. Gardez un seul client par processus (code plus bas).
  • Une rafale plus large que le bassin. Un Promise.all sur 50 requêtes, ou une page qui lance 30 recherches d’un coup, demandent toutes une connexion en même temps. Avec un bassin de 9, 41 attendent. Si les 9 premières sont lentes, les autres expirent.
  • Des requêtes lentes qui gardent les connexions. Une requête de 4 secondes occupe sa connexion 4 secondes. Dix comme ça, et un bassin de 10 est plein. Hausser la limite masque le problème jusqu’à ce que le trafic augmente. Trouvez-les avec pg_stat_statements.
  • De longues transactions interactives. prisma.$transaction(async (tx) => …) garde une connexion du début à la fin, y compris pendant un fetch ou tout autre travail lent fait à l’intérieur. Sortez la partie lente de la transaction.
  • Un bassin dimensionné pour la mauvaise machine. La valeur par défaut de Prisma 6 compte les cœurs que voit le processus. Déplacez la même appli sur un plus gros hôte et le bassin grossit avec elle, parfois au-delà de ce que la base permet.
// lib/prisma.ts: one client for the whole process
import { PrismaClient } from "@prisma/client";

const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };

export const prisma = globalForPrisma.prisma ?? new PrismaClient();

// Dev hot reload would otherwise create a new client (and pool) per reload
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

Prisma 7 a confié le bassin au pilote

Dans Prisma ORM 7, Postgres passe par un adaptateur de pilote comme @prisma/adapter-pg, et le bassin est celui du pilote. La documentation de Prisma dit que les valeurs par défaut « viennent maintenant du pilote lui-même ». Pour pg, deux choses changent : le bassin contient 10 connexions, peu importe le nombre de processeurs, et le délai d’acquisition est de 0, ce qui veut dire qu’une requête attend indéfiniment au lieu d’échouer.

Avec Prisma 7 et pg, vous ne verrez donc peut-être jamais P2024. L’épuisement du bassin se manifeste par des requêtes qui figent. Si vous fixez connectionTimeoutMillis, l’erreur devient celle de pg : timeout exceeded when trying to connect.

Prisma 6 (paramètre d’URL)Par défautPrisma 7 avec pg (champ de l’adaptateur)Par défaut
connection_limit † †Cœurs physiques × 2 + 1max10
pool_timeout † † †10 sconnectionTimeoutMillis0 (aucun délai)
max_idle_connection_lifetime † †300 sidleTimeoutMillis10 s
P2024 à l’expiration † †Ouitimeout exceeded when trying to connectSeulement une fois un délai fixé

† Les détails sur les concurrents proviennent des pages publiées par chaque fournisseur aux dates indiquées; les prix et forfaits changent, vérifiez auprès du fournisseur avant de décider. `connection_limit` (2026-10-29) · `connection_limit` (2026-10-29) · `pool_timeout` (2026-10-29) · `pool_timeout` (2026-10-29) · `pool_timeout` (2026-10-29) · `max_idle_connection_lifetime` (2026-10-29) · `max_idle_connection_lifetime` (2026-10-29) · P2024 à l’expiration (2026-10-29) · P2024 à l’expiration (2026-10-29)

Dimensionner le bassin, avec Prisma 6 et 7

Pour un serveur de longue durée, Prisma conseille de partir du bassin par défaut divisé par le nombre d’instances de l’appli. En pratique, partez de la base : prenez le nombre de connexions qu’elle permet, soustrayez ce dont le reste a besoin (migrations, un deuxième processus, psql) et donnez le reste à l’appli.

Si votre plateforme injecte DATABASE_URL, pas besoin de modifier la variable. Fixez les paramètres dans le code :

// Prisma 6: set the pool in code when DATABASE_URL is injected for you
const url = new URL(process.env.DATABASE_URL!);
url.searchParams.set("connection_limit", "10");
url.searchParams.set("pool_timeout", "20"); // seconds

export const prisma = new PrismaClient({ datasourceUrl: url.toString() });

// Prisma 7: the pool belongs to the driver adapter (here, pg)
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "./generated/prisma";

const adapter = new PrismaPg({
  connectionString: process.env.DATABASE_URL,
  max: 10,                        // was connection_limit
  connectionTimeoutMillis: 10_000, // was pool_timeout; pg's default 0 waits forever
});

export const prisma = new PrismaClient({ adapter });

Sans serveur ou longue durée : des points de départ différents

Reprendre les conseils pour le sans serveur sur un serveur de longue durée est une erreur courante. connection_limit=1 sur un serveur Node fait attendre chaque requête pour l’unique connexion, ce qui transforme une rafale de trafic en file de P2024.

Où roule l’appliPoint de départ de PrismaPourquoi
Fonctions sans serveur, sans regroupeur externe †connection_limit=1, puis ajusterChaque invocation simultanée est un processus distinct avec son propre bassin. Une pointe de trafic les multiplie.
Fonctions sans serveur derrière un regroupeur (PgBouncer, Supavisor) †Le bassin par défaut, puis ajuster. Ajoutez pgbouncer=true si le regroupeur est en mode transactionLe regroupeur partage quelques connexions serveur entre de nombreux clients.
Un seul serveur de longue durée †Le bassin par défaut, ou le défaut ÷ nombre d’instancesUn processus, un bassin, des connexions réutilisées d’une requête à l’autre.
CannerBassin de 8 : la production et un aperçu tiennent tous deux dans les 20, avec de la marge pour les migrations et psqlUn processus de longue durée par projet, jusqu’à 20 connexions par base.

† Les détails sur les concurrents proviennent des pages publiées par chaque fournisseur aux dates indiquées; les prix et forfaits changent, vérifiez auprès du fournisseur avant de décider. Fonctions sans serveur, sans regroupeur externe (2026-10-29) · Fonctions sans serveur derrière un regroupeur (PgBouncer, Supavisor) (2026-10-29) · Un seul serveur de longue durée (2026-10-29)

Prisma chez Canner

Un projet Canner exécute un seul processus de longue durée, et sa base accepte jusqu’à 20 connexions en même temps (documentation des tâches en arrière-plan). DATABASE_URL donne à chaque connexion sa propre session Postgres : n’ajoutez pas pgbouncer=true, ce paramètre vise les regroupeurs en mode transaction.

  • Fixez le bassin explicitement. La valeur par défaut de Prisma 6, basée sur les processeurs, reflète le serveur où atterrit votre processus, pas votre forfait. Un connection_limit=8 fixe (ou max: 8 avec Prisma 7) se comporte pareil partout.
  • Gardez une marge pour la commande de mise en production. prisma migrate deploy roule pendant que la version actuelle sert encore, et ouvre sa propre connexion (où lancer les migrations).
  • Comptez les aperçus. Un déploiement d’aperçu partage les variables d’environnement du projet : c’est un deuxième processus, avec son propre bassin, sur la même base.
  • Si 20 ne suffit plus, la réponse chez Canner, ce sont des requêtes moins nombreuses et plus rapides, pas plus de connexions. Si votre architecture a besoin de nombreux processus sur une même base en même temps, Canner ne convient pas aujourd’hui.

Questions

Faut-il mettre pool_timeout=0 pour éviter P2024?

Seulement pour un traitement par lots où attendre ne pose pas problème, comme une grosse importation avec beaucoup de requêtes en parallèle. Prisma le documente pour ce cas. Sur un serveur web, une erreur claire devient une requête qui fige.

Est-ce que connection_limit=1 règle P2024?

Sur des fonctions sans serveur sans regroupeur, c’est le point de départ recommandé par Prisma. Sur un serveur de longue durée, c’est pire : toutes les requêtes du processus se partagent une seule connexion.

Pourquoi P2024 n’arrive-t-il qu’en développement avec Next.js?

Le rechargement à chaud réexécute le module qui crée PrismaClient, et chaque nouveau client ouvre son propre bassin pendant que les anciens traînent. Gardez le client sur globalThis hors production, comme dans l’extrait plus haut.

Prisma 7 lance-t-il encore P2024?

Avec un adaptateur de pilote, le bassin est celui du pilote. Avec pg, le délai d’acquisition par défaut est de 0 : les requêtes attendent au lieu d’échouer. Fixez connectionTimeoutMillis et vous obtenez l’erreur de pg « timeout exceeded when trying to connect ».

Quel connection_limit utiliser chez Canner?

8 pour une appli. La base permet jusqu’à 20 connexions, et un aperçu est un deuxième processus avec son propre bassin : à 8 chacun, les deux tiennent, avec de la marge pour les migrations et toute session psql.

Faites rouler votre appli Prisma à côté de sa base.

Chaque projet reçoit une base Postgres à Montréal. Déployez depuis le terminal avec la CLI Canner.