Quick verdict
Choose PgBouncer when the problem is too many connections: its transaction pooling lets many clients share a few server connections, and it has little to configure. Choose Pgpool-II when you want one middleware layer to send writes to the primary, spread reads across streaming replicas and react to a failed primary, and you are ready to manage many more settings. Both are free and open source. They are not mutually exclusive: some teams run PgBouncer for pooling in front of, or alongside, a separate routing and failover layer.
PgBouncer is an open source connection pooler for PostgreSQL under the ISC licence. Clients connect to it as if it were PostgreSQL and it hands out server connections from pools keyed by user and database. It offers three modes: session (the default), transaction and statement pooling. The current release is 1.26.1 (14 October 2026); 1.26.0 (23 September 2026) removed the old online restart option -R, and the changelog now points to rolling restarts with so_reuseport instead.
Pgpool-II, from the PgPool Global Development Group, is PostgreSQL middleware under a short BSD-style licence. Besides connection reuse it parses statements, routes writes to the primary and reads to standbys, checks replication delay, performs automatic failover and online recovery, offers an in-memory query cache, and coordinates several Pgpool-II nodes through a watchdog with a virtual IP. The current release is 4.7.3 (29 September 2026), with the 4.3 to 4.6 branches updated the same day.
A pooler and a proxy are different jobs. PgBouncer is a pooler: it reduces server connections but does not decide where a query should run. Pgpool-II is a SQL-aware proxy that also pools. For a managed AWS option, see Amazon RDS Proxy vs PgBouncer.
Side by side
| Aspect | PgBouncer | Pgpool-II |
|---|---|---|
| Product type | Connection pooler only | Middleware: pooling, routing, load balancing, failover, query cache |
| Pooling modes | Session (default), transaction and statement | Per-child-process connection cache reused by later clients with the same user, database and protocol; no transaction pooling documented |
| Server connections used | Bounded by pool settings such as default_pool_size per user and database | Up to num_init_children x max_pool per backend (max_pool default 4) |
| Read/write splitting | No; point clients at separate logical databases for primary and replicas | Yes: parses SQL, sends writes to the primary and balances reads in streaming_replication mode |
| Load balancing | Host list per database with load_balance_hosts (round-robin, or stick to one host); no role awareness | Weighted read balancing per session or per statement, preference lists by database, application or user, replication delay check |
| Failover | No primary detection; usually paired with Patroni, DNS, a virtual IP or HAProxy | Automatic failover and online recovery of PostgreSQL nodes |
| High availability of the middleware itself | Run several instances (so_reuseport on one host, or several hosts behind a balancer) | Watchdog with virtual IP; at least three Pgpool-II nodes recommended to avoid split brain |
| Prepared statements | Protocol-level prepared statements in transaction mode since 1.21 (max_prepared_statements, default 200) | Sessions keep their backend connections, so session features work as on PostgreSQL |
| Authentication | cert, md5, scram-sha-256, trust, hba, ldap, pam; auth_file or auth_query | trust, password, md5, scram-sha-256, cert, PAM and LDAP; GSSAPI not supported |
| Licence and price | ISC licence, free | BSD-style licence, free |
| Main trade-off | Simple and efficient at pooling, but routing and HA are someone else's job | One layer for routing and HA, but many parameters to get right and weaker connection savings |
Key differences
How each one saves connections
PgBouncer separates client connections from server connections. In transaction pooling a server connection is lent to a client only for the length of one transaction and then returned, so a few dozen server connections can serve far more clients. The cost is that session state does not survive between transactions: SET, LISTEN, session advisory locks and SQL-level PREPARE are not safe in this mode, although protocol-level prepared statements, which most drivers use, are supported since 1.21. Version 1.26.0 also began tracking every parameter PostgreSQL reports, including search_path on PostgreSQL 18, so settings do not leak between clients.
Pgpool-II works with a pool of child processes. Each child serves one client at a time and keeps up to max_pool cached backend connections; a later client with the same user, database and protocol version reuses one of them. The documentation warns that total backend connections can reach num_init_children times max_pool. Because a client holds its child for the whole session, this cuts connection setup cost but does not multiplex many concurrent clients onto fewer server connections the way PgBouncer transaction pooling does. The upside is that session features behave as they do on a direct connection.
Routing reads and writes
This is the main reason to choose Pgpool-II. In the recommended streaming_replication clustering mode, PostgreSQL replicates on its own and Pgpool-II inspects each statement: writes and anything inside an explicit write transaction go to the primary, while reads can be balanced across standbys by weight, either per session or per statement (statement_level_load_balance). Preference lists can send a given database, application name or user to particular nodes, write_function_list marks functions that modify data, and delay_threshold sends reads back to the primary when a standby lags.
PgBouncer does not look inside queries. You can define one logical database that points at the primary and another that points at replicas, and the application chooses which to use. A comma-separated host list with load_balance_hosts (added in 1.24.0) spreads new server connections across hosts, but PgBouncer does not know which host is the primary.
; pgbouncer.ini: separate entries for writes and reads
[databases]
app = host=pg-primary port=5432 dbname=app
app_ro = host=pg-replica1,pg-replica2 port=5432 dbname=app
[pgbouncer]
pool_mode = transaction
default_pool_size = 20 Failover and high availability
Pgpool-II includes automatic failover (it can run a failover command when a backend fails), online recovery to bring a node back, and a watchdog that lets several Pgpool-II nodes share a virtual IP so the middleware is not a single point of failure. The watchdog needs at least three nodes to avoid split brain, which adds hosts and configuration. Teams often combine it with external tooling or let Pgpool-II drive promotion, and it is important that only one component is in charge of failover.
PgBouncer has no failover logic. The common pattern is to let Patroni or a managed service handle promotion and to point PgBouncer at a stable endpoint such as a virtual IP, a DNS name or HAProxy. PgBouncer itself is usually made highly available by running more than one instance. Note that 1.26.0 removed online restart (-R), so upgrades now rely on rolling restarts with so_reuseport or on several instances behind a balancer.
Operational complexity
PgBouncer has a short configuration file, an admin console with SHOW commands, and online reload for most settings. It is single-threaded, using one CPU core per process, so heavy deployments run several processes with so_reuseport. Pgpool-II has many more parameters and five clustering modes, and its documentation is correspondingly long. A wrong setting can send writes to the wrong node or serve stale reads, so treat its configuration as part of your database design and review it with each release branch.
Pricing and licensing
Both are free. PgBouncer is distributed under the ISC licence (COPYRIGHT file in the GitHub repository) and the project sells no paid edition. Pgpool-II is distributed under a BSD-style permission notice published on pgpool.net, and the project sells nothing either. Your costs are the servers or containers you run them on and the staff time to operate them. A Pgpool-II watchdog setup needs at least three nodes; PgBouncer is often run as a sidecar or on the application or database hosts. Some managed PostgreSQL services include PgBouncer in their own pricing; check your provider.
Pricing checked on the vendors' official pages on 7 November 2026. Prices change; confirm before buying.
Where each one leads
PgBouncer strengths
- Transaction pooling lets many clients share a small number of server connections
- Small, single-purpose and quick to configure, with packages on most Linux distributions
- Protocol-level prepared statements work in transaction mode since 1.21
- Wide choice of authentication methods, including auth_query, LDAP (1.25.0) and PAM
- Widely used, including inside several managed PostgreSQL services
Pgpool-II strengths
- SQL-aware read/write splitting and weighted read load balancing
- Replication delay check that keeps reads on the primary when standbys lag
- Automatic failover, online recovery and a watchdog for its own high availability
- In-memory query cache for repeated SELECT statements
- Session features behave as on a direct connection, because clients keep their backend connection
Limitations
PgBouncer limitations
- No read/write splitting or primary detection
- Transaction and statement modes break SET, LISTEN, session advisory locks and SQL PREPARE
- Single-threaded per process; scaling across cores needs several processes
- Online restart was removed in 1.26.0, so plan rolling upgrades
Pgpool-II limitations
- Many parameters and modes; misconfiguration can misroute writes or serve stale reads
- Connection cache per child process saves fewer server connections than transaction pooling
- Watchdog high availability needs at least three Pgpool-II nodes
- GSSAPI authentication is not supported
When to choose each
Choose PgBouncer if
- You hit max_connections from autoscaled application servers, workers or serverless functions
- Your application is stateless enough for transaction pooling
- Failover is already handled by Patroni, a managed service or a virtual IP
- You want a small component with little to configure and patch
Choose Pgpool-II if
- You run a primary with streaming replicas and want reads spread without changing the application
- You want one middleware layer to follow a failed primary
- You need routing by database, application name or user, or a replication lag threshold
- You want a query cache for repeated reads
When neither is right
- You are on AWS and prefer a managed pooler with IAM authentication: see Amazon RDS Proxy vs PgBouncer.
- A single-threaded pooler has become the bottleneck: compare Odyssey vs PgBouncer.
- You only need TCP failover to whichever node is primary: a generic balancer such as HAProxy with health checks from your HA manager may be enough.
- Your application servers already pool connections well and the server is not near its limit: driver-side pooling may be all you need.
Final recommendation
If your PostgreSQL server is running out of connections, PgBouncer is the more direct fix: transaction pooling saves far more connections than a per-process cache, and there is little to configure. If you need the middleware itself to split reads from writes, balance across replicas and react to failover, Pgpool-II is the more complete tool, at the price of a much larger configuration surface. Decide which component owns failover first, then pick the pooler or proxy that fits around it.
Frequently asked questions
Can I use PgBouncer and Pgpool-II together?
Yes, some teams do: PgBouncer handles transaction pooling close to the application and Pgpool-II handles routing and failover in front of the database servers. It adds a hop and two sets of configuration, so only do it when you need both jobs done.
Does Pgpool-II do transaction pooling like PgBouncer?
No transaction-level pooling is documented. Pgpool-II caches backend connections per child process (up to max_pool each) and reuses one when a later client has the same user, database and protocol version. A client keeps its child process for the session.
Does PgBouncer split reads and writes?
No. It does not parse queries or know which host is the primary. You can define separate logical databases for the primary and for replicas and have the application choose, or use a SQL-aware proxy such as Pgpool-II.
Which one is easier to run?
PgBouncer, by a wide margin: it has a short configuration and a single job. Pgpool-II has five clustering modes and many parameters, and a watchdog setup needs at least three nodes.
What changed in PgBouncer 1.26?
Version 1.26.0 (23 September 2026) tracks all parameters PostgreSQL reports by default, including search_path, adds pool_idle_timeout and per-user query_wait_timeout, and removes online restart (-R); the changelog recommends rolling restarts with so_reuseport. 1.26.1 (14 October 2026) fixed three security issues.
Sources
- PgBouncer features and pooling modes
- PgBouncer configuration reference
- PgBouncer changelog
- PgBouncer licence (COPYRIGHT file)
- Pgpool-II home page and releases
- Pgpool-II licence
- Pgpool-II documentation: clustering modes
- Pgpool-II documentation: connection pooling
- Pgpool-II documentation: load balancing
- Pgpool-II documentation: authentication methods
Checked November 2026.
How we research comparisons: our editorial method.