Pic de trafic : deux cents processus PHP-FPM actifs, chacun ouvre une nouvelle connexion à la base. PostgreSQL atteint sa limite de cent connexions — trop de connexions. Panique : on monte la limite à cinq cents. La mémoire de la base explose, le système bascule sur le disque, les performances empirent.
PgBouncer arrive : deux cents clients applicatifs, trente connexions PostgreSQL réelles. La crise semble résolue — jusqu'au jour où trente requêtes lentes simultanées bloquent tout le pool pendant trente secondes. L'application expire en masse. Le pool a masqué le plafond de connexions, pas la capacité de traitement concurrent de la base.
Le pool de connexions résout le coût d'ouverture. Il ne résout pas les analyses complètes de table. Mal réglé, il ajoute une file d'attente invisible devant une base déjà suffoquée.
Où placer le pool dans la stack
Selon votre environnement, l'outil change ; le principe reste le même : une couche entre les processus applicatifs et la base.
| Stack | Outil courant |
|---|---|
| PHP / Python / Node → PostgreSQL | PgBouncer devant PostgreSQL |
| MySQL | ProxySQL, MariaDB MaxScale, ou pool applicatif |
| Fonctions sans serveur | Pooler obligatoire (proxy managé) |
| PHP sans pooler | Connexions persistantes — risque de connexions zombies |
Architecture typique :
[PHP-FPM × N] → [PgBouncer :6432] → [PostgreSQL :5432]
Ne doublez pas les pools applicatif et PgBouncer sans comprendre la chaîne — des pools imbriqués créent latence et interblocages.
Dimensionnement : partir de la base, pas de l'application
Pour PostgreSQL, le nombre optimal de connexions actives se mesure sous charge réelle — pas sur une feuille de calcul théorique. En pratique, default_pool_size entre vingt et cinquante suffit souvent pour une PME ; max_client_conn doit couvrir la somme des processus applicatifs.
| Symptôme | Cause probable |
|---|---|
| Timeout de file pool | Pool trop petit ou requêtes trop longues |
| Processeur base bas, timeouts app | Requêtes bloquées par verrous |
| « Trop de connexions » | Contournement du pool ou mauvaise configuration |
Mode transaction : gains et pièges
Le poolage par transaction recycle la connexion PostgreSQL après validation. N'utilisez pas ce mode avec des requêtes préparées liées à la session, des variables de session persistantes, ou des fonctionnalités comme écoute et notification. Le mode session est plus sûr pour migrer ; le mode transaction après audit de votre couche d'accès aux données.
Sur hébergement mutualisé MySQL, les connexions sont souvent limitées à dix ou trente : un pool côté application est obligatoire. Sur PostgreSQL managé, un pooler est parfois inclus — vérifiez les limites de votre offre et mesurez la file d'attente avant de monter en charge matérielle.
En pratique, la plupart des incidents « pool » disparaissent après optimisation des requêtes lentes : index manquants, jointures non filtrées, transactions trop longues. Le pool devient alors un amortisseur utile plutôt qu'un plafond de verre.
Le sommet : le pool déplace la saturation
Ordre de correction : requêtes lentes → pool → montée en charge base. Inverser l'ordre, c'est payer file d'attente et matériel supplémentaire pour le même résultat.
Décider et avancer sans angle mort
Mesurez le nombre de connexions PostgreSQL ou MySQL au pic actuel avant tout changement. Déployez PgBouncer ou ProxySQL si vos processus applicatifs dépassent largement un max_connections sûr. Fixez pool_size à partir de la capacité réelle de la base, pas du nombre de workers. Surveillez clients en attente et temps moyen d'attente. Analysez les requêtes les plus lourdes en parallèle — voir EXPLAIN PostgreSQL et saturation PHP-FPM.
Questions fréquentes
Pourquoi pooler PostgreSQL ?
Chaque connexion consomme de la mémoire ; le pool multiplexe des centaines de processus applicatifs sur moins de connexions serveur.
Session vs transaction mode PgBouncer ?
Le mode transaction est plus efficace ; le mode session reste plus compatible avec les outils de mapping objet-relationnel.
Comment dimensionner pool_size ?
Partez de la capacité processeur de la base, mesurez sous charge réelle, pas du nombre de workers applicatifs.
Le pool remplace-t-il index SQL ?
Non — les requêtes lentes restent lentes une fois connectées. Optimisez les requêtes en premier.
Le pool de connexions soigne l'ouverture — pas la requête qui étouffe la base une fois connectée.