Skip Navigation
Show nav
Heroku Dev Center Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
Heroku Dev Center Dev Center
  • 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 in or Sign up
View 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
    • Buildpacks
  • Developer Tools
    • AI 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 Rails
      • 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
      • Working with PHP
      • PHP Behavior in Heroku
    • 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
    • Inference Essentials
    • Inference API
    • Inference Quick Start Guides
    • AI Models
    • Tool Use
    • AI Integrations
    • Vector Database
  • 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
  • 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
    • Heroku AppLink
      • Getting Started with Heroku AppLink
      • Working with Heroku AppLink
      • Heroku AppLink Reference
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Other Salesforce Integrations
  • Language Support
  • Scala
  • Database Connection Pooling with Scala

Database Connection Pooling with Scala

English — 日本語に切り替える

Table of Contents [expand]

  • Using Apache DBCP
  • Configure the Connection Pool
  • Limit Connections with PgBouncer

Last updated February 26, 2026

Connection pooling uses a pre-created set of reusable connection objects to connect to databases. Instead of opening a new connection for every request, your application retrieves one from the pool and returns it when done. This reduces network traffic, lowers the cost of creating connections, and eases garbage collector load.

Many Scala and Java frameworks include their own connection pooling APIs, but the configuration principles are the same. This guide shows how to create a database connection pool using JDBC and the Apache DBCP pooling library.

This guide assumes you have an existing Scala application that uses JDBC. You should also be familiar with Connecting to Relational Databases on Heroku with Java.

Using Apache DBCP

Open your application’s build.sbt file and add the following libraries to it.

libraryDependencies ++= Seq(
  "org.postgresql" % "postgresql" % "42.7.10",
  "org.apache.commons" % "commons-dbcp2" % "2.14.0"
)

Run sbt to download and install the new dependencies:

$ sbt clean compile

Next, open the source code for the class that creates connections and add the following import:

import org.apache.commons.dbcp2._

Then add a new singleton object to contain and configure the database connection pool at the end of the file:

object Datasource {
  val connectionPool = new BasicDataSource()
  connectionPool.setUrl(System.getenv("JDBC_DATABASE_URL"))
  connectionPool.setInitialSize(3)
}

The JDBC_DATABASE_URL environment variable is set automatically by Heroku and contains the full JDBC connection string including credentials. setInitialSize(3) sets the initial size of the pool. The BasicDataSource object immediately creates these connections so they’re ready when your application starts receiving traffic.

Retrieve a connection from the pool like so:

val connection = Datasource.connectionPool.getConnection

val statement = connection.createStatement()
statement.executeUpdate("CREATE TABLE IF NOT EXISTS ticks (tick timestamp)")
statement.executeUpdate("INSERT INTO ticks VALUES (now())")
val resultSet = statement.executeQuery("SELECT tick FROM ticks")

while (resultSet.next()) {
  println("Read from DB: " + resultSet.getTimestamp("tick"))
}

Once you have a connection object, use it exactly the same as any other JDBC Connection.

In addition to the initial size, you can configure the pool’s maximum size, the maximum lifetime of connections (before they’re discarded and replaced), and the minimum and maximum number of idle connections. Set all of these with methods on the BasicDataSource class.

Configure the Connection Pool

The number of idle connections to keep warm in your pool depends on the size and nature of your application. Many users find one connection per thread handling HTTP requests is sufficient (assuming threads handling HTTP requests are the only threads using connections). Your application may need more if it experiences very high throughput such that it can’t turn connections over to new threads quick enough. Or you may need fewer if not every HTTP request needs to access the database. Ultimately, profiling your application under production loads is the best way to determine the appropriate pool parameters.

In development you can see the number of connections used by your application by checking the database.

$ psql -h localhost

This opens a connection to your development database. You can then see the number of connections to your Postgres database by running:

select count(*) from pg_stat_activity where pid <> pg_backend_pid() and usename = current_user;

This returns the number of connections on that database:

 count
-------
   5
(1 row)

Under simulated production loads, this gives you a good indication of what size pool you need. There are, however, some constraints.

Maximum Database Connections

Heroku provides managed Postgres databases. Different tiered databases have different connection limits, listed on the Heroku Postgres add-on page. Lower tiers permit fewer connections than higher tiers. Once your database reaches the maximum number of active connections, it no longer accepts new connections, resulting in connection timeouts and exceptions in your application.

When scaling out, it is important to keep in mind how many active connections your application needs. If each dyno allows 5 database connections, you can only scale out to four dynos before you need to provision a more robust database.

With this knowledge, calculate the right number of connections each dyno needs based on your database’s connection limit.

Limit Connections with PgBouncer

You can scale out your applications with additional dynos until you reach your database connection limits. Before that point, we recommend limiting the number of connections required by each dyno using the classic PgBouncer buildpack. There is no Cloud Native Buildpack for PgBouncer.

PGBouncer maintains a pool of connections that your database transactions share. This keeps connections to Postgres, which are otherwise open and idle, to a minimum. However, transaction pooling prevents you from using named prepared statements, session advisory locks, listen/notify, or other features that operate on a session level. See the PgBouncer buildpack FAQ for full list of limitations for more information.

For many frameworks, you must disable prepared statements in order to use PGBouncer. Then set your app to use a custom buildpack that will call other buildpacks.

For JDBC, this requires adding prepareThreshold=0 to the connection string. But it may also be necessary to patch your JDBC driver.

Do not continue before disabling prepared statements, or verifying that your framework is not using them.

$ heroku buildpacks:add heroku/pgbouncer

Next, add the Scala buildpack so your application can build:

$ heroku buildpacks:add heroku/scala

Now modify your Procfile to start PgBouncer by adding bin/start-pgbouncer-stunnel to the beginning of your web entry. For example, change:

web: target/universal/stage/bin/scala-getting-started

To:

web: bin/start-pgbouncer-stunnel target/universal/stage/bin/scala-getting-started

Commit the results to git, test on a staging app, and then deploy to production.

For more information on connection pooling with JDBC and Apache DBCP, see the Apache Commons DBCP documentation.

Feedback

Log in to submit feedback.

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
  • © 2026 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