Qu'est-ce que le pooling de connexions serverless ?

Mis à jour : septembre 2026

Le pooling de connexions serverless est une technique qui partage quelques connexions réelles à la base entre de nombreuses instances de fonctions éphémères. Il existe parce que deux modèles de mise à l’échelle ne s’accordent pas : le calcul serverless répond à la charge en multipliant les instances, alors qu’une base de données traite chaque connexion comme une ressource coûteuse, adossée à de la mémoire et soumise à un plafond strict. Associez naïvement les deux, et un pic de trafic modeste se transforme en panne too many connections.

Points clés

QuestionRéponse
La collisionLes fonctions montent en charge par clonage ; les connexions sont plafonnées et coûteuses
Le symptômeFATAL: sorry, too many clients already pendant les pics
La solutionUn pooler multiplexe de nombreux clients sur quelques connexions réelles
Le réglagePooling en mode transaction vs. session — partage vs. compatibilité
La réponse BaaSLes clients parlent HTTPS sans état ; la plateforme gère le pool

La panne, vue depuis la base de données

-- Ce que voit la base de données pendant un pic de trafic serverless :
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state;
--  active               |   14
--  idle                 |  483     ← immobilisées par les instances de fonctions chaudes
SHOW max_connections;    --  100    ← le plafond qu'elles ont déjà largement dépassé

-- Chaque connexion est un vrai processus qui occupe de la vraie mémoire —
-- c'est pourquoi le plafond existe, et pourquoi le relever n'est pas la solution.

La forme du problème : chaque instance de fonction ouvre sa propre connexion, la conserve pendant les temps morts entre deux invocations, et le nombre d’instances est dicté par le trafic, pas par vous. La réutilisation n’a lieu qu’au sein d’une instance chaude — jamais d’une instance à l’autre — donc une concurrence de 300 signifie 300 pools à connexion unique. Relever max_connections achète de la marge au prix d’une vraie consommation mémoire, et perd face au pic suivant, plus gros.

Sur un backend géré, le code applicatif sort complètement de ce combat — les appels SDK sont des requêtes HTTPS sans état, et aucun client ne détient jamais de connexion à la base de données :

// JavaScript / Node.js — Back4app JS SDK
// Inside a serverless function: no driver, no pool, no connection to leak.
// Each SDK call is a stateless HTTPS request; pooling happens platform-side.
Parse.initialize('APP_ID', 'JS_KEY');
Parse.serverURL = 'https://parseapi.back4app.com';

export async function handler(event) {
  const query = new Parse.Query('Order');
  query.equalTo('status', 'pending');
  query.limit(20);
  const orders = await query.find();  // request returns; nothing stays open
  return orders.map((o) => o.id);
}
// 1,000 concurrent invocations = 1,000 HTTP requests,
// not 1,000 database connections.

Comment un pooler absorbe le fan-out

Pooler de connexions entre les fonctions serverless et la base de donnéesDes centaines d'instances de fonctions éphémères ouvrent des connexions client peu coûteuses vers un pooler, qui les multiplexe sur un petit ensemble fixe de connexions réelles à la base de données, maintenant la base sous son plafond de connexions.

20 connexions réelles

les clients patientent brièvement
au lieu d'échouer

Fonction ×500
(pic)

Pooler
(p. ex. PgBouncer)

Fonction ×500
(pic suivant)

Base de données
max_connections: 100

Des centaines d'instances de fonctions éphémères ouvrent des connexions client peu coûteuses vers un pooler, qui les multiplexe sur un petit ensemble fixe de connexions réelles à la base de données, maintenant la base sous son plafond de connexions.

Un pooler comme PgBouncer accepte les connexions client par milliers — chacune peu coûteuse de son côté — et ne prête des connexions serveur réelles, issues d’un petit pool, qu’au moment où du travail arrive. La base voit vingt connexions tranquilles ; cinq cents fonctions croient chacune en avoir une. Quand la demande dépasse le pool, les clients attendent quelques millisecondes dans une file au lieu de recevoir des erreurs — une défaillance franche se convertit en latence modeste.

Le dimensionnement du pool est l’endroit où l’intuition échoue le plus. Le parallélisme utile d’une base de données est borné par ses cœurs et ses disques — le débit culmine généralement avec un pool de quelques dizaines de connexions, autour du nombre de cœurs multiplié par deux, puis chute à mesure que les connexions supplémentaires ajoutent de la contention. L’arithmétique du pooler fonctionne parce que les requêtes serverless sont courtes : une connexion qui sert une transaction de 8 ms peut en servir bien plus d’une centaine par seconde, si bien que vingt connexions réelles absorbent sans peine des milliers d’invocations de fonctions. Le pool n’est pas un cache de confort ; c’est un goulot d’étranglement délibéré, placé là où la mise en file d’attente coûte peu.

Le réglage décisif, c’est la durée du bail.

Pooling en mode transaction vs. pooling en mode session

DimensionPooling en mode sessionPooling en mode transaction
Durée du bailToute la session du clientUne transaction, puis récupération
Facteur de partageFaible — les clients inactifs immobilisent des connexionsÉlevé — idéal pour le travail serverless court
Prepared statementsPleinement pris en chargeUniquement via un support au niveau du protocole, configuré explicitement
État de session (SET, tables temporaires, LISTEN/NOTIFY)FonctionneCassé — des transactions différentes peuvent tomber sur des connexions différentes
Idéal pourApps de longue durée, outils d’administration, migrationsTrafic requête/réponse web et serverless

Le mode transaction est ce qui rend les workloads serverless viables — une fonction qui exécute une transaction de 8 ms ne devrait pas monopoliser une connexion pendant ses plusieurs minutes de vie à chaud — mais il n’est pas gratuit : tout ce qui suppose que « ma connexion » persiste d’une instruction à l’autre devient un bug subtil. La recommandation habituelle : pooling en mode transaction pour le trafic de requêtes, connexion directe ou en mode session pour les migrations et tout ce qui porte un état.

Cas d’usage courants

  • Fonctions serverless et edge qui interrogent du SQL. Le cas canonique — des nombres d’instances en dents de scie face à un budget de connexions fixe.
  • Beaucoup de petits services, une seule base. Vingt services × des pools par défaut de dix connexions = 200 connexions que personne n’a prévues ; un pooler partagé rétablit une arithmétique raisonnable.
  • Plateformes multi-tenant. Les workloads par tenant multiplient la demande en connexions ; le pooling permet de faire respecter le budget de la base partagée.
  • Rafales de trafic sur des bases modestes. Les pics du jour de lancement patientent quelques millisecondes au pooler au lieu de provoquer des erreurs dans la base.
  • Protéger la base primaire pendant les incidents. Un pool de taille fixe est une cloison étanche : les clients incontrôlés épuisent la file du pooler, pas la mémoire de la base.

Devriez-vous exploiter votre propre pooler ? Matrice de décision

Exploitez un pooler quand…Passez-vous-en quand…
Des fonctions ou de nombreux services se connectent directement au SQLUn BaaS géré termine le trafic client dans sa couche API
Des erreurs de connexion apparaissent lors des pics de chargeLe trafic est régulier et provient de quelques serveurs de longue durée dotés de pools côté client
Vous exploitez la base de données et son budgetLa plateforme fait déjà le pooling entre le tier API et la base
Des tenants ou des équipes partagent une même baseLe workload se résume à une app, un pool, bien en deçà des limites
Vous pouvez exploiter un composant critique de plusPersonne n’est d’astreinte pour le pooler

L’asymétrie, en toute honnêteté : un pooler résout l’épuisement des connexions ; un backend géré le fait disparaître. Quand les clients parlent HTTPS à des API générées automatiquement, le fan-out n’atteint jamais la couche base de données — le pooling a toujours lieu, mais sous la forme d’une infrastructure éprouvée gérée par quelqu’un d’autre plutôt que d’un composant à votre charge.

Limites et trade-offs

  • Un pooler est un composant. Il faut le déployer, le superviser, prévoir son basculement et le mettre à jour — vous avez échangé un problème de ressources contre un problème d’exploitation, à un taux favorable mais non nul.
  • Le mode transaction modifie la sémantique. Prepared statements, variables de session et advisory locks cessent de se comporter comme documenté ; les échecs sont intermittents et dépendent de la charge — la pire espèce.
  • Un saut supplémentaire coûte de la latence. Généralement moins d’une milliseconde au sein du réseau, mais il se trouve sur le chemin de chaque requête.
  • Le pooler peut devenir le goulot d’étranglement. Un pooler mono-thread soumis à un pic violent accumule une file profonde ; le plafond s’est déplacé, il n’a pas disparu.
  • Le pooling ne corrige pas les requêtes lentes. Il rationne les connexions ; une requête qui garde son bail pendant des secondes affame le pool. Des requêtes rapides — et les index qui les sous-tendent — restent le vrai levier de capacité.

Pooling de connexions sur Back4app

Back4app est une plateforme open-source de Backend as a Service (BaaS) qui combine une base de données gérée, des API REST et GraphQL générées automatiquement, l’authentification, le stockage de fichiers et des fonctions serverless avec Cloud Code. Son architecture répond structurellement à la question du pooling : les apps clientes et les fonctions Cloud Code émettent des requêtes HTTPS sans état, et c’est le tier serveur de la plateforme — pas votre code — qui maintient des pools de connexions durables et correctement dimensionnés vers la base de données gérée. Le fan-out des instances côté calcul ne se traduit jamais en fan-out de connexions côté base de données, ce qui est exactement la propriété que tout cet article cherche à construire.

Questions fréquentes

Pourquoi le serverless épuise-t-il les connexions à la base de données ?

Parce que deux modèles de mise à l'échelle entrent en collision : le calcul serverless multiplie les instances au rythme des requêtes, alors qu'une base de données dispose d'un budget de connexions fixe — souvent autour de 100 par défaut. Chaque instance de fonction ouvre sa propre connexion et la conserve pendant ses temps morts, si bien qu'un pic de trafic qui lance 500 instances réclame 500 connexions d'un coup. La base refuse l'excédent, et des requêtes sans aucun rapport se mettent à échouer.

Que fait concrètement un pooler de connexions comme PgBouncer ?

Il se place entre votre code et la base de données, accepte des milliers de connexions client peu coûteuses et les multiplexe sur un petit pool de connexions serveur réelles. Les clients croient détenir une connexion ; en réalité, ils en empruntent une le temps d'une transaction ou d'une session, puis la rendent. La base voit un ensemble de connexions stable et fixe, quel que soit le nombre de fonctions qui démarrent.

Quelle différence entre le pooling en mode transaction et le pooling en mode session ?

La durée du bail. Le pooling en mode session attribue une connexion réelle pour toute la session du client — compatible avec toutes les fonctionnalités, mais un client inactif immobilise quand même une connexion. Le pooling en mode transaction ne prête la connexion que pendant l'exécution d'une transaction, puis la récupère, ce qui démultiplie le partage mais casse l'état de session : prepared statements, variables de session et LISTEN/NOTIFY demandent des précautions, sinon ils échouent.

Pourquoi les connexions explosent-elles quand les fonctions montent en charge ?

Une plateforme serverless gère la concurrence en clonant des instances, et chaque clone initialise son propre client de base de données. La réutilisation des connexions n'a lieu qu'au sein d'une même instance chaude, jamais d'une instance à l'autre. Une concurrence de 300 signifie donc 300 pools de taille un — la pire forme possible : tout le surcoût du pooling, sans aucun partage. Ce fan-out est structurel, pas un bug de votre code.

Quelle taille donner à un pool de connexions ?

Bien plus petite que l'intuition ne le suggère. Le débit culmine généralement avec un pool proche du parallélisme réel de la base — une règle empirique courante est le nombre de cœurs multiplié par deux, ajusté selon les attentes disque — et non de plusieurs centaines. Au-delà, les connexions supplémentaires ajoutent de la contention et de la mémoire sans ajouter de débit. Le rôle du pooler est précisément de donner aux appelants l'impression qu'un petit pool est infini.

Ai-je encore besoin d'un pooler avec un BaaS ?

Pas pour votre propre trafic — c'est tout l'intérêt. Un backend géré termine les requêtes client sous forme d'appels HTTPS sans état dans sa couche API ; son propre tier serveur maintient vers la base des pools durables et correctement dimensionnés. Vos fonctions et vos apps ne détiennent jamais de connexion à la base, si bien que le scénario d'épuisement disparaît au lieu d'être atténué. Les poolers ne redeviennent utiles que si vous connectez directement des outils externes.

Quels sont les inconvénients des poolers de connexions ?

Ils ajoutent un saut réseau et donc de la latence, deviennent un composant à exploiter et à superviser, et le mode transaction modifie discrètement la sémantique — les fonctionnalités liées à la session cessent de se comporter comme documenté. Un processus pooler unique peut lui-même devenir le goulot d'étranglement sous une charge en pics, et un mauvais dimensionnement ne fait que déplacer la file d'attente. C'est une infrastructure essentielle, mais c'est une infrastructure.

Termes associés

À comparer avec

Lectures recommandées

Prêt à construire votre backend ?

Lancez votre projet sur Back4app en quelques minutes — base de données, authentification, API et Cloud Code inclus. Sans carte bancaire.

Écrit et révisé par Back4app Engineering, Back4app Engineering · Publié le 2026-09-16