PgBouncer vs Supavisor vs PgCat : quel pooler Postgres en 2026
PgBouncer, Supavisor et PgCat mutualisent tous les trois des connexions Postgres, mais ils ne visent pas le même problème. PgBouncer reste le standard historique : léger, en C, intégré nativement à l'écosystème Kubernetes via CloudNativePG. Supavisor a été construit par Supabase pour un besoin précis, faire tenir des milliers de bases tenant derrière un seul service au lieu d'un process par base. PgCat, écrit en Rust, ajoute au pooling classique du sharding et de l'équilibrage de charge entre réplicas. Chez Aurabase, le trafic data-plane passe par PgBouncer en mode transaction. C'est ce que montre directement le code du dépôt : chart Helm, ressource CNPG Pooler et docker-compose local convergent tous vers le même choix.
Cet article compare l'architecture des trois poolers : langage, modes de pooling, modèle mono ou multi-tenant, fonctions au-delà du pooling pur. Tembo et PkgPulse ont publié des comparatifs chiffrés de ces trois outils, mais nous n'avons reproduit aucune de leurs mesures nous-mêmes. Notre position éditoriale sur les benchmarks, détaillée dans notre méthodologie de benchmark, est de ne jamais republier un chiffre qu'on n'a pas vérifié soi-même. Ce que vous trouverez ici à la place : l'architecture réelle de chaque outil, et la façon dont Aurabase route concrètement son trafic Postgres, vérifiée section par section dans le code source.
- PgBouncer (C) reste le pooler le plus éprouvé et le mieux intégré à Kubernetes : CloudNativePG s'appuie directement dessus pour sa ressource
Pooler. - Supavisor (Elixir, projet Supabase) cible un problème différent : servir des milliers de bases tenant depuis un même service, plutôt qu'un pooler par base.
- PgCat (Rust) ajoute au pooling brut du sharding applicatif, de l'équilibrage de charge entre réplicas et du failover automatique.
- Le dépôt Aurabase montre PgBouncer utilisé à deux niveaux : un déploiement partagé pour la flotte mutualisée, et une ressource
Poolergérée par CloudNativePG par tenant dédié. Les deux tournent en mode transaction. - PostgREST et le pool d'administration d'
aura-dbrestent volontairement en connexion directe sur Postgres, sans passer par le pooler : le transaction pooling casserait leur rechargement de schéma et leurs verrous de session.
Trois poolers, trois philosophies
PgBouncer minimise, Supavisor mutualise à l'échelle du multi-tenant, PgCat ajoute des fonctions réseau au pooling brut. Aucun des trois n'est un remplacement direct des deux autres, même s'ils sont souvent comparés terme à terme sur les mêmes pages.
Colonnes, dans l'ordre : PgBouncer, Supavisor, PgCat. Caractéristiques d'architecture d'après les dépôts officiels de chaque projet, à confirmer sur la version que vous déployez, l'écosystème évoluant vite sur ce point.
Le standard historique, léger et intégré à Kubernetes
PgBouncer ne fait qu'une chose : mutualiser des connexions Postgres, sans fonction annexe. Ce périmètre volontairement étroit explique en grande partie sa longévité et son adoption comme brique de base dans la plupart des stacks Postgres en production.
Trois modes de pooling sont disponibles. Le mode session ouvre une connexion serveur par connexion client, le plus permissif. Le mode transaction réutilise une connexion serveur entre plusieurs clients, libérée à chaque fin de transaction. Le mode statement va plus loin encore, et reste rarement utilisé en production. C'est le mode transaction qui apporte le vrai gain de mutualisation, mais il impose des règles strictes. Tout état de session (variables SET, verrous consultatifs, LISTEN/NOTIFY) ne survit pas au-delà d'une transaction. Nous détaillons ces règles et leurs pièges dans notre article dédié sur le mode transaction pooling de PgBouncer.
Historiquement mono-processus, une instance PgBouncer exploite un seul cœur CPU par défaut. Faire tourner plusieurs instances derrière le même port (via SO_REUSEPORT) est une évolution plus récente du projet, pas une caractéristique de conception initiale. Côté authentification, PgBouncer supporte un auth_query configurable, une fonction SQL exécutée à chaque connexion pour résoudre dynamiquement le mot de passe d'un rôle. Ce mécanisme évite de dépendre d'un fichier statique listant chaque utilisateur à l'avance. C'est exactement ce mécanisme qu'Aurabase utilise pour ses rôles par-projet (section 05).
Pooler. Sur un cluster Postgres géré par l'opérateur CloudNativePG, activer un pooler managé revient, en pratique, à activer PgBouncer sans le configurer à la main.Le pooler multi-tenant cloud-native de Supabase
Supavisor répond à un problème que PgBouncer n'a jamais été conçu pour résoudre à cette échelle. Il s'agit de servir un très grand nombre de bases tenant distinctes depuis un service unique, plutôt qu'une instance de pooler par base. Écrit en Elixir et exécuté sur la machine virtuelle Erlang (BEAM), le projet est développé et maintenu par Supabase, en open source, sur son propre dépôt GitHub.
Le modèle multi-tenant natif est la vraie différence structurelle. Là où une flotte PgBouncer classique demande un process (ou un ensemble de connexions dédiées) par base cible, Supavisor fonctionne différemment. Il enregistre dynamiquement des tenants via une interface d'administration HTTP, et route chaque connexion entrante vers la bonne base sans redémarrer le service. Supabase a migré ses propres projets Cloud de PgBouncer vers Supavisor pour cette raison précise. Un cluster de pooling classique, un par base, ne passe pas à l'échelle d'un cloud multi-tenant qui héberge des centaines de milliers de projets.
Ce choix architectural a un revers documenté. La parité de fonctionnalités avec PgBouncer sur des cas avancés a mis du temps à se stabiliser après le lancement du projet. Deux exemples : certains comportements de LISTEN/NOTIFY, et la gestion fine des prepared statements en mode transaction. À vérifier sur votre version avant migration si votre application dépend de ces comportements précis.
L'outsider Rust : sharding et load-balancing natifs
PgCat se positionne explicitement comme une alternative à PgBouncer, écrite en Rust. Il ajoute au pooling classique des fonctions réseau que ni PgBouncer ni Supavisor n'embarquent nativement. Trois en particulier : sharding applicatif par clé de partition, équilibrage de charge entre réplicas de lecture, et bascule automatique loin d'un réplica en échec. Le projet est né chez Instacart avant d'être repris et maintenu aujourd'hui par PostgresML.
Concrètement, PgCat peut jouer le rôle qu'occuperaient normalement deux couches distinctes : un pooler de connexions et un proxy applicatif de routage entre plusieurs instances Postgres. Une équipe qui shardait déjà ses données à la main peut simplifier son code avec PgCat. Même chose pour une logique de répartition des lectures entre réplicas développée en interne : une couche réseau dédiée la remplace directement.
Le compromis inverse existe aussi : PgCat est un projet plus jeune, avec un écosystème de documentation et de retours d'expérience en production nettement plus restreint que PgBouncer. Adopter ses fonctions de sharding et de failover, c'est aussi accepter de dépendre de la maturité de ce composant précis, pas seulement de sa capacité de pooling.
Ce que montre le code Aurabase : PgBouncer partout, sauf où le transaction pooling casse tout
Le dépôt Aurabase déploie PgBouncer à deux niveaux distincts, tous deux en mode transaction. Pour la flotte mutualisée, le chart Helm définit un déploiement PgBouncer dédié devant le data-plane partagé (deploy/helm/aurabase/templates/infra/pgbouncer.yaml, image edoburu/pgbouncer). Pour un tenant sur instance dédiée, le provisioner génère une ressource Pooler gérée nativement par CloudNativePG (deploy/cnpg/tenant-pooler.yaml, rendue par k8s_tenant.rs). Aucun des deux ne fait appel à Supavisor ni à PgCat. Le code ne documente pas de comparatif explicite ayant précédé ce choix. Il montre en revanche une intégration profonde et déjà opérationnelle avec l'écosystème CloudNativePG, cohérente avec le fait que PgBouncer en est la brique de pooling native.
Tout ne passe pourtant pas par le pooler, et c'est un choix délibéré documenté dans le code lui-même. PostgREST reste connecté en direct sur Postgres, jamais via PgBouncer. Le commentaire du chart Helm est explicite sur la raison : le transaction pooling casserait son rechargement de schéma, qui dépend d'un LISTEN sur le canal pgrst. Ce mécanisme est incompatible avec des connexions serveur recyclées entre clients. Le pool d'administration d'aura-db (schéma, DDL, verrous consultatifs de session) reste lui aussi en connexion directe, pour la même raison de fond. Un SET search_path non transaction-scoped et des verrous de session ne survivent pas à un pooler en mode transaction.
L'authentification suit le pattern auth_query décrit en section 02 : AUTH_QUERY: SELECT * FROM pgbouncer.user_lookup($1), sans fichier userlist.txt statique. C'est ce qui permet aux rôles créés dynamiquement par projet (project_<uuid>_authenticator) de s'authentifier via PgBouncer sans redéployer le pooler à chaque nouveau projet.
healthcheck PgBouncer dans docker-compose.yml documente un bug réel, déjà corrigé. Un pg_isready exécuté contre PgBouncer valide seulement la poignée de main du proxy, jamais la connexion réelle au backend Postgres qu'il relaie. PgBouncer répond « accepting connections » même backend arrêté, en mettant les requêtes en file d'attente. Résultat observé lors d'un test destructif : le service restait healthy pendant 5 cycles consécutifs alors que Postgres était injoignable. Le correctif remplace le check par une vraie requête psql de bout en bout à travers le pooler, jusqu'au backend. Résultat après correction, dans le même test rejoué : unhealthy détecté en 7 cycles, environ 35 secondes.Un dernier détail, mineur mais révélateur : le chart Helm épingle edoburu/pgbouncer:v1.24.1-p1 par défaut, tandis que le docker-compose local utilise v1.25.2-p0. Ce n'est pas un choix architectural, juste un léger défaut de synchronisation de versions entre deux environnements, le genre de détail qu'une revue de code attrape plus vite qu'un article de blog. Nous le documentons tel quel plutôt que de le maquiller. Pour le détail du cloisonnement par schéma que ce pooler dessert, voir notre article sur l'isolation RLS multi-tenant.
- Cluster Postgres géré par CloudNativePG ou Kubernetes en général
- Vous voulez le pooler le plus éprouvé et le mieux documenté
- Une base cible par instance de pooler vous convient
- Des centaines ou milliers de bases tenant derrière un même service
- Besoin d’enregistrer des tenants dynamiquement via une API, sans redéploiement
- Déjà dans l’écosystème Supabase ou disposé à en dépendre
- Sharding applicatif déjà en place ou prévu au niveau du pooler
- Équilibrage de charge et failover réplica sans couche applicative séparée
- À l’aise avec un projet plus jeune, moins documenté que PgBouncer
Quel que soit le pooler retenu, il ne remplace pas le dimensionnement de Postgres lui-même. La taille du pool et le max_connections du serveur doivent être pensés ensemble, pas l'un après l'autre. Un pool généreux devant un max_connections trop bas se contente de déplacer la saturation d'un étage à l'autre. Notre guide sur le tuning de max_connections détaille la formule de dimensionnement à appliquer avant de fixer la taille de votre pool.
Ce qu'on nous demande le plus souvent
Il n'y a pas de pooler universel, seulement un bon fit pour votre tenance
PgBouncer, Supavisor et PgCat résolvent trois variantes du même problème, pas trois versions du même outil. PgBouncer reste le choix le plus sûr quand votre plateforme s'appuie déjà sur Kubernetes et CloudNativePG, ou quand vous voulez simplement le pooler le plus documenté. Supavisor devient pertinent au-delà d'un certain nombre de bases tenant à servir depuis un même service. PgCat vaut le détour si le sharding et le failover réplica vous manquent au niveau réseau, à condition d'accepter la maturité d'un projet plus jeune.
Le code Aurabase montre un choix cohérent, pas neutre : PgBouncer en mode transaction, à deux niveaux, flotte partagée et pooler CNPG par tenant dédié. Deux exceptions documentées subsistent, pour PostgREST et pour l'administration du schéma. Si vous voulez voir ce cloisonnement par projet à l'œuvre plutôt que sur le papier, notre page Performances documente la méthodologie de mesure associée.
Comment choisir entre les trois