Last updated May 29, 2026
Server-side connection pooling for Heroku Postgres helps applications use database connections efficiently to avoid reaching your database’s plan connection limits. It also optimizes your database resources. Use connection pooling to connect to your Heroku Postgres database via PgBouncer, a service that maintains its own connection pool. PgBouncer directs your app’s queries to existing open database connections, reducing the frequency with which your database server creates new processes and reuses established connections that otherwise remain idle.
Because PgBouncer’s connection pool exists on the database server, both your app and any external apps that communicate with your database can share the same pool of connections.
For client-side connection pooling, see Running PgBouncer on a Dyno.
Server-side connection pooling isn’t supported on Heroku Postgres Advanced (Limited GA). Subscribe to our changelog to stay informed of when this feature is available for Advanced databases.
Check Connection Pooling Availability
Server-side connection pooling is available for Standard, Premium, Private, and Shield-tier databases.
Use the heroku pg:info command to check whether connection pooling is available for your database. If it is, the Connection Pooling field shows Available:
$ heroku pg:info -a example-app
=== DATABASE_URL
Plan: Standard 0
Status: Available
Data Size: 39.9 MB / 64 GB (0.06%)
Tables: 39
PG Version: 16.13
Connections: 11/400
Connection Pooling: Available
(...)
Server-side connection pooling isn’t available for Essential-tier databases. For client-side connection pooling, see Running PgBouncer on a Dyno.
Enable Connection Pooling
Enable server-side connection pooling for your database with the heroku pg:connection-pooling:attach command:
$ heroku pg:connection-pooling:attach DATABASE_URL --as DATABASE_CONNECTION_POOL -a example-app
Enabling Connection Pooling on ⛁ postgresql-octagonal-12345 to ⬢ example-app... done
Setting DATABASE_CONNECTION_POOL config vars and restarting ⬢ example-app... done, v1182
This command adds a config var called DATABASE_CONNECTION_POOL_URL, based on the default DATABASE_CONNECTION_POOL attachment alias. You can specify a different alias with the --as option, which creates a config var named as the alias with _URL appended. Your app can use the resulting connection pool URL to connect to the database like any other Postgres URL. Unlike your default database connection string, the connection pooling URL points to port 5433 where the server-side PgBouncer service is accepting connections.
We recommend using the default name DATABASE_CONNECTION_POOL_URL. Connection poolers under this name automatically get reattached to the new leader when using heroku pg:promote.
At the moment, server-side connection pooling doesn’t support multiple pools. You can attach connection pooling under multiple names, but they point to the same PgBouncer pool.
Share Connection Pools Between Your Apps
To share your Heroku Postgres database with another app through connection pooling, use heroku pg:connection-pooling:attach on the app that you want to connect. Reference your add-on either by add-on name or using the app-name::ATTACHMENT-NAME convention. You can also specify the attachment name as an alias for your add-on using the --as flag:
$ heroku pg:connection-pooling:attach main-database-app::DATABASE_URL --as EXTERNAL_CONNECTION_POOL -a other-app
Enabling Connection Pooling on ⛁ postgresql-octagonal-12345 to ⬢ other-app... done
Setting EXTERNAL_CONNECTION_POOL config vars and restarting ⬢ other-app... done, v84
To stop sharing connection pooling with another app, use the heroku addons:detach command, specifying an existing connection pool attachment:
$ heroku addons:detach EXTERNAL_CONNECTION_POOL --app other-app
Detaching EXTERNAL_CONNECTION_POOL to postgresql-octagonal-85179 from ⬢ other-app... done
Unsetting EXTERNAL_CONNECTION_POOL config vars and restarting ⬢ other-app... done, v85
Use Connection Pooling in Your App
Many frameworks automatically use the DATABASE_URL environment variable to connect to a database. For your app to connect to the connection pooler instead, make sure your app is using the connection pooling config var to get your database connection string.
For example, for Ruby on Rails in config/database.yml, where the connection pooling attachment is DATABASE_CONNECTION_POOL_URL:
production:
url: <%= ENV['DATABASE_CONNECTION_POOL_URL'] || ENV['DATABASE_URL'] %>
prepared_statements: false
advisory_locks: false
Remove Connection Pooling
You can remove the connection pooling attachment with the heroku addons:detach command. Make sure your app isn’t using the connection pool config var to connect to the database as it’s unset.
$ heroku addons:detach DATABASE_CONNECTION_POOL --app example-app
Detaching DATABASE_CONNECTION_POOL to postgresql-octagonal-85179 from ⬢ example-app... done
Unsetting DATABASE_CONNECTION_POOL config vars and restarting ⬢ example-app... done, v1183
View Connection Pool Info
Connect to PgBouncer’s admin console to review your pool statistics, configuration, and further PgBouncer details.
To connect to PgBouncer’s internal database via psql, get your connection pool’s database URL using port 5433. Then, replace the final component of the URL, the database name, to point it to the /pgbouncer database:
$ heroku run bash -a example-app
Running bash on ⬢ example-app... up, run.7383 (Private-M)
$ psql postgres://username:password@ec2-192-168-1-1.compute-1.amazonaws.com:5433/pgbouncer?sslmode=require
psql (17.2 (Postgres.app), server 1.24.1/bouncer)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off, ALPN: none)
Type "help" for help.
pgbouncer=#
Several commands are available to retrieve operational information from PgBouncer, such as SHOW VERSION and SHOW STATS. A full list of commands is available in PgBouncer’s documentation.
The Heroku Postgres metrics logs provide a subset of the PgBouncer metrics reported by the SHOW POOLS; and SHOW STATS; commands.
View Version
Run SHOW version; to check the PgBouncer version:
pgbouncer=# SHOW version;
version
------------------
PgBouncer 1.24.1
(1 row)
View Connection Pooling Stats
Run SHOW STATS; to view information about pgbouncer’s throughput:
pgbouncer=# SHOW STATS
-[ RECORD 1 ]-----------------+---------------
database | d9fm5ro65cprs0
total_server_assignment_count | 8047
total_xact_count | 8047
total_query_count | 8047
total_received | 112658
total_sent | 1745781
total_xact_time | 8036019
total_query_time | 8036019
total_wait_time | 4091285
(...)
Version Support
Heroku Postgres supports PgBouncer version 1.24.
See View Version to check your PgBouncer’s version.
Caveats
Incompatibility with pg:credentials
Connection pooling only supports a single connection pool associated with the default database credential. Connection pooling is incompatible with non-default credentials.
Incompatibility with Advisory Locks
Connection pooling and connections to Heroku Postgres through PgBouncer aren’t compatible with advisory locks.
Incompatibility with mTLS
Connection pooling isn’t compatible with database connections received via mTLS.
Incompatibility with Heroku Connect
Heroku Connect uses session variables in PostgreSQL triggers. These variables are incompatible with the transaction pooling mode used in connection pooling.
You can still enable connection pooling on databases with Heroku Connect if:
- You use
SET LOCALinstead ofSET SESSIONin custom triggers with Heroku Connect. - The number of mappings is less than 25% of your database plan’s connection limit. Heroku Connect uses one direct connection per mapping. Too many mappings cause connection issues as only 25% of database connections are reserved for direct connections when you enable connection pooling.
If you enable connection pooling on databases with Heroku Connect:
- Configure Heroku Connect to use a direct connection to the database. For example,
DATABASE_URL. - Configure your other database connections to use the connection pool. For example,
DATABASE_CONNECTION_POOL_URL
Load
If your app is under high load, we recommend monitoring PgBouncer stats. We recommend monitoring transactions per second, since connection queuing can increase when the PgBouncer process sits above ~15-20k xact/s.
Some Variables Don’t Work as Expected with Ruby
Some Postgres session variables and variables listed in the Rails database.yml file don’t work with PgBouncer.
Limits
Client Connection Limits
When your app connects to the pooler, it can open up to 10,000 simultaneous connections.
Server Connection Limits
When the pooler connects to your database, it can open up to 75% of your database plan’s connection limit. For example, if your database is on a standard-4 plan with a limit of 500 connections, the pooler can open up to 375 connections to Postgres.
The remaining 25% of your server connections are reserved for direct connections from your app. This limit is useful for app processes that are incompatible with the connection pooler, such as Heroku Connect, or other connections that require the use of session variables.
Max Prepared Statements
You can have up to 200 protocol-level prepared statements while using PgBouncer with Heroku Postgres. Manual PREPARE commands via SQL aren’t compatible with PgBouncer on Heroku Postgres.
Pooling Modes
Connection pooling for Heroku Postgres uses PgBouncers’ transaction pooling mode. See here for an in-depth discussion of pooling modes and their capabilities and caveats.
Running PgBouncer on a Dyno
Heroku offers a classic buildpack to run PgBouncer on your app’s dynos for client-side connection pooling. This buildpack can help reduce TCP overhead on high-concurrency processes that use multiple database connections. There’s currently no Cloud Native Buildpack for PgBouncer.