PgBouncer acts as a Postgres server, so simply point your client to the PgBouncer port.
PgBouncer does not have an internal multi-host configuration. It is possible via external tools:
DNS round-robin. Use several IPs behind one DNS name. PgBouncer does not look up DNS each time a new connection is launched. Instead, it caches all IPs and does round-robin internally. Note: if there are more than 8 IPs behind one name, the DNS backend must support the EDNS0 protocol. See README for details.
Use a TCP connection load-balancer. Either
HAProxy seem to be good choices. On the
PgBouncer side it may be a good idea to make
and also turn
server_round_robin on: by default, idle connections
are reused by a LIFO algorithm, which may work not so well when
load-balancing is needed.
PgBouncer does not have internal failover-host configuration nor detection. It is possible with external tools:
DNS reconfiguration: When the IP address behind a DNS name is
reconfigured, PgBouncer will reconnect to the new server. This
behaviour can be tuned by two configuration parameters:
dns_max_ttl tunes the lifetime for one host name, and
dns_zone_check_period tunes how often a zone SOA will be queried
for changes. If a zone SOA record has changed, PgBouncer will
re-query all host names under that zone.
Write a new host to the configuration and let PgBouncer reload it:
send SIGHUP or use the
RELOAD command on the console. PgBouncer
will detect a changed host configuration and reconnect to the new
RECONNECT command. This is meant for situations where
neither of the two options above are applicable, for example when
you use the aforementioned HAProxy to route connections downstream
RECONNECT simply causes all server connections
to be reopened. So run that after that other component has changed
its connection routing information.
In session pooling mode, the reset query must clean old prepared
statements. This can be achieved by
server_reset_query = DISCARD ALL;
or at least to
To make prepared statements work in this mode would need PgBouncer to keep track of them internally, which it does not do. So the only way to keep using PgBouncer in this mode is to disable prepared statements in the client.
The proper way to do it for JDBC is adding the
parameter to the connection string.
To disable use of server-side prepared statements, the PDO attribute
PDO::ATTR_EMULATE_PREPARES must be set to
true. Either at
$db = new PDO("dsn", "user", "pass", array(PDO::ATTR_EMULATE_PREPARES => true));
[ This cannot be done with TLS connections. ]
This is as easy as launching a new PgBouncer process with the
switch and the same configuration:
$ pgbouncer -R -d config.ini
-R (reboot) switch makes the new process connect to the console
of the old process (dbname=pgbouncer) via the Unix socket and issue
the following commands:
SUSPEND; SHOW FDS; SHUTDOWN;
After that, if the new one notices that the old one is gone, it
resumes work with the old connections. The magic happens during the
SHOW FDS command which transports the actual file descriptors to new
If the takeover does not work for whatever reason, the new process can be simply killed. The old one notices this and resumes work.
SHOW CLIENTS and
SHOW SERVERS commands on the console.
link to map local client connection to server
port of client connection to identify TCP
connection from client.
local_port to identify TCP connection to
Installing PgBouncer on the web server is good when short-lived connections are used. Then the connection setup latency is minimised. (TCP requires a couple of packet roundtrips before a connection is usable.) Installing PgBouncer on the database server is good when there are many different hosts (e.g., web servers) connecting to it. Then their connections can be optimised together.
It is also possible to install PgBouncer on both web server and database server. One negative aspect of that is that each PgBouncer hop adds a small amount of latency to each query.
In the end, you will need to test which model works best for your performance needs. You should also consider how installing PgBouncer will affect the failover of your applications in the event of a web server vs. database server going away.