Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Working with Node.js
      • Troubleshooting Node.js Apps
      • Node.js Behavior in Heroku
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Model Context Protocol
    • Vector Database
    • Heroku Inference
      • Inference API
      • Quick Start Guides
      • AI Models
      • Inference Essentials
    • Working with AI
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Databases & Data Management
  • Heroku Postgres
  • Postgres Performance
  • Client-Side Postgres Connection Pooling

Client-Side Postgres Connection Pooling

English — 日本語に切り替える

Last updated January 24, 2025

Table of Contents

  • Configuration
  • Language/Library Specific Configuration
  • Tweak Settings
  • Caveats

Heroku provides a buildpack to run PgBouncer alongside application code. It’s meant to be used in conjunction with other buildpacks.

The primary use of the buildpack is to allow for transaction pooling of PostgreSQL database connections among multiple workers in a dyno. For example, 10 unicorn workers would be able to share a single database connection, avoiding connection limits and Out Of Memory errors on the Postgres server.

The buildpack’s source code can be found on GitHub.

This article is only applicable for apps using classic buildpacks. There currently is no Cloud Native Buildpack version for PgBouncer, and isn’t compatible with Fir-generation apps.

Why Should I Use Connection Pooling?

You have many workers per dyno that hold open idle connections and you’re concerned about Postgres reaching connection limits.

See this answer on Stack Overflow for more advantages of connection pooling.

See the Caveats section for more information.

Configuration

Add the PgBouncer buildpack to your app.

$ heroku buildpacks:add --index 1 heroku/pgbouncer

Edit the Procfile and add bin/start-pgbouncer to the appropriate lines. The following example configures web processes to connect to Postgres via PgBouncer and worker processes to connect directly to Postgres.

web: bin/start-pgbouncer your-web-app
worker: your-worker-app

Commit your changes and push. Your app is now using PgBouncer to connect to Postgres.

$ git commit -av -m "web processes now use PgBouncer"
$ git push heroku

All connections PgBouncer and Postgres require SSL.

Connecting to Multiple Databases

It’s possible to connect to multiple databases through PgBouncer by setting PGBOUNCER_URLS to a list of config vars.

$ heroku config:add PGBOUNCER_URLS="DATABASE_URL HEROKU_POSTGRESQL_ROSE_URL"

Follower Replica Databases

Where possible, we changed noninclusive terms to align with our company value of Equality. We retained noninclusive terms to document a third-party system, but we encourage the developer community to embrace more inclusive language. We’ll update the term when it’s no longer required for technical accuracy.

If you’re using Octopus Replication to send reads to a replica, make sure to include the color URL of your leader in the SLAVE_DISABLED_FOLLOWERS blocklist. Otherwise, Octopus attempts to use your leader as a read-only replica, potentially doubling your connection count.

Language/Library Specific Configuration

Set ignore_startup_parameters for Certain Postgres Drivers

Some drivers, like Go’s pq driver, include extra_float_digits in the URI used to connect to Postgres. Using the buildpack with these drivers requires setting an extra config variable.

$ heroku config:set PGBOUNCER_IGNORE_STARTUP_PARAMETERS=extra_float_digits

This command adds ignore_startup_parameters = extra_float_digits to PgBouncer’s config file when a dyno is started.

Unexpected Session Configuration in ORMs

Some ORMs, like ActiveRecord before v4.2.5, can set session variables during queries to ensure consistency. While this can be useful when connecting to postgres directly, it can cause unexpected behavior and difficult-to-diagnose errors with transactional connection pooling. Make sure you thoroughly test applications before moving to connection pooling, including auditing ORM code for any “overly helpful” session configuration.

An example of these problems can be found in the GoCardless Engineering Blog.

SSL Mode for Go’s pq driver

Using Go’s pq driver with the PgBouncer buildpack results in the following error. This occurs because on-dyno PgBouncer doesn’t have access to the server’s certificates.

pq: SSL is not enabled on the server

Set the following environment variable for connections to succeed.

$ heroku config:set PGSSLMODE=disable

Your connections are still secure. Pgbouncer uses native TLS to connect to Postgres itself. Setting PGSSLMODE only disables TLS connections from the application to pgbouncer.

Disable Prepared Statements in Rails

With Rails 4.1, you can disable prepared statements by appending ?prepared_statements=false to the database’s URI.

Rails versions 4.0.0–4.0.3, reportedly can’t disable prepared statements at all. Make sure your framework is up to date before troubleshooting prepared statements failures.

Rails 3.2–4.0 also requires an initializer to properly cast the prepared_statements configuration string as a boolean. This initializer is adapted from this commit. In file config/initializers/database_connection.rb insert the following:

require "active_record/connection_adapters/postgresql_adapter"

class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
  alias initialize_without_config_boolean_coercion initialize
  def initialize(connection, logger, connection_parameters, config)
    if config[:prepared_statements] == 'false'
      config = config.merge(prepared_statements: false)
    end
    initialize_without_config_boolean_coercion(connection, logger, connection_parameters, config)
  end
end

Tweak Settings

Some settings are configurable through app config vars at runtime. Refer to the appropriate documentation for PgBouncer to see which settings are right for you.

Either config variables or in-line environment variables in Procfile works for configuration settings. See PgBouncer Configuration for configuring the default settings.

Via config variables:

$ heroku config:set PGBOUNCER_POOL_MODE=session

Via in-line environment variables:

web: PGBOUNCER_POOL_MODE=session bin/start-pgbouncer

Configurable Settings

PGBOUNCER_AUTH_TYPE

Default is scram-sha-256. You can change to md5 or plain depending on server support.

PGBOUNCER_SERVER_TLS_SSLMODE

Default is require

PGBOUNCER_POOL_MODE

Default is transaction

PGBOUNCER_MAX_CLIENT_CONN

Default is 100

PGBOUNCER_DEFAULT_POOL_SIZE

Default is 1

PGBOUNCER_MIN_POOL_SIZE

Default is 0

PGBOUNCER_RESERVE_POOL_SIZE

Default is 1

PGBOUNCER_RESERVE_POOL_TIMEOUT

Default is 5.0 seconds

PGBOUNCER_SERVER_LIFETIME

Default is 3600.0 seconds

PGBOUNCER_SERVER_IDLE_TIMEOUT

Default is 600.0 seconds

PGBOUNCER_URLS

Contains all config variables that are overridden to connect to PgBouncer. For example, set this variable to AMAZON_RDS_URL to send RDS connections through PgBouncer. The default is DATABASE_URL.

PGBOUNCER_CONNECTION_RETRY

The default is no

PGBOUNCER_LOG_CONNECTIONS

The default is 1. If your app doesn’t use persistent database connections, this setting can be noisy and must be set to 0.

PGBOUNCER_LOG_DISCONNECTIONS

The default is 1. If your app doesn’t use persistent database connections, this setting can be noisy and must be set to 0.

PGBOUNCER_LOG_POOLER_ERRORS

Default is 1

PGBOUNCER_STATS_PERIOD

Default is 60

PGBOUNCER_SERVER_RESET_QUERY

The default is empty when pool mode is transaction, and DISCARD ALL; when session.

PGBOUNCER_IGNORE_STARTUP_PARAMETERS

Adds parameters to ignore when PgBouncer is starting. Some Postgres libraries, like Go’s pq, append this parameter, making it impossible to use this buildpack. The default is empty and the most commonly ignored parameter is extra_float_digits.

Multiple parameters can be separated via commas.

Example: PGBOUNCER_IGNORE_STARTUP_PARAMETERS="extra_float_digits, some_other_param"

Caveats

Refer to PGBouncer’s feature matrix for all connection pooling caveats.

Incompatibility with Prepared Statements and Advisory Locks

Connection pooling and connections to a PostgreSQL through pgbouncer aren’t compatible with prepared statements and advisory locks.

Incompatibility with LISTEN and NOTIFY

Connection pooling and connections to a PostgreSQL through pgbouncer aren’t compatible with PostgreSQL’s LISTEN and NOTIFY.

Keep reading

  • Postgres Performance

Feedback

Log in to submit feedback.

Understanding Heroku Postgres Data Caching Correctly Establishing Postgres Connections in Forked Environments

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices