Generic Best Practices for HikariCP with Azure Database for PostgreSQL

Author: Mohamed Baioumy
Technology: Azure Database for PostgreSQL (Flexible Server & Single Server)
Category: Connectivity | Performance | Application Design

Introduction

Connection pooling is a critical component of application performance when connecting to Azure Database for PostgreSQL. Creating a new PostgreSQL connection is an expensive operation that consumes CPU, memory, and networking resources. Reusing existing connections through a connection pool significantly reduces connection latency, improves throughput, and helps applications scale more efficiently.

Many Java applications use HikariCP, one of the most popular high-performance JDBC connection pools. While HikariCP provides excellent performance out of the box, improperly configured connection pool settings can lead to issues such as:

  • Connection pool exhaustion
  • Stale or invalid connections
  • Increased connection acquisition latency
  • Excessive connection creation and destruction
  • Database resource contention
  • Application timeouts

This article summarizes generic guidance and best practices for configuring HikariCP when working with Azure Database for PostgreSQL Flexible Server and Azure Database for PostgreSQL Single Server.

Understanding Key HikariCP Parameters

1. Maximum Lifetime (maxLifetime)

The maxLifetime property controls how long a connection can remain in the pool before HikariCP retires it and creates a new one.

Why It Matters

Connections can become stale over time due to:

  • Network interruptions
  • Infrastructure updates
  • Connection state changes
  • TCP idle behavior

Recycling connections periodically helps prevent applications from using long-lived connections that may no longer be healthy.

Recommended Practice

Avoid configuring the value too low.

When maxLifetime is set aggressively, HikariCP continuously destroys and recreates connections, resulting in:

  • Additional authentication overhead
  • Increased connection establishment latency
  • Higher CPU utilization
  • Reduced application throughput

A reasonable starting point is:

spring.datasource.hikari.maxLifetime=1800000

30 minutes (1,800,000 ms) is commonly used and aligns well with many production workloads. Depending on workload characteristics, values between 30 minutes and 1 hour are generally suitable

Avoid

maxLifetime=300000

(5 minutes)

This often causes unnecessary connection churn without providing additional benefits.

2. Minimum Idle Connections (minimumIdle)

The minimumIdle setting defines how many idle connections HikariCP should keep ready for immediate use.

Why It Matters

A pool with available idle connections can serve application requests immediately without waiting for new connections to be established.

However, maintaining too many idle connections consumes unnecessary database resources.

Recommended Practice

For most workloads:

minimumIdle = maximumPoolSize

Or

minimumIdle slightly lower than maximumPoolSize

This ensures sufficient connections are already available during traffic spikes while avoiding excessive connection creation delays.

Example

maximumPoolSize=20
minimumIdle=15

Avoid

maximumPoolSize=20
minimumIdle=20

only when the application experiences long periods of inactivity and conserving resources is more important than immediate responsiveness.

3. Idle Timeout (idleTimeout)

The idleTimeout property determines how long an unused connection remains in the pool before being removed.

Why It Matters

Connections that sit idle for extended periods consume resources on both:

  • The application server
  • Azure Database for PostgreSQL

However, removing idle connections too quickly causes the application to repeatedly establish new connections.

Recommended Practice

Keep the default value unless there is a specific requirement.

spring.datasource.hikari.idleTimeout=600000

which equals:

10 minutes (600,000 ms)

This setting provides a good balance between resource utilization and responsiveness. [Re: EXT: R…0040002947 | Outlook]

The timeout should also be comfortably longer than any expected short application idle periods.

Avoid

idleTimeout=10000

(10 seconds)

Such aggressive settings often result in unnecessary connection creation cycles.

4. Maximum Pool Size (maximumPoolSize)

This parameter determines the maximum number of concurrent database connections the application can maintain.

Why It Matters

This is often the most important HikariCP setting.

If the Pool Is Too Small

Applications may experience:

Connection is not available, request timed out

because all available connections are already in use. Similar scenarios have been observed during customer investigations involving Hikari pool exhaustion.

If the Pool Is Too Large

Applications can overwhelm the database server with excessive concurrent sessions, resulting in:

  • Connection contention
  • Increased context switching
  • Higher memory consumption
  • Reduced overall performance

Recommended Practice

Pool size should be based on:

  • Database compute configuration
  • CPU core count
  • Query execution duration
  • Application concurrency requirements
  • Workload characteristics

There is no universal value that fits every workload.

Start conservatively:

maximumPoolSize=10

or

maximumPoolSize=20

maximumPoolSize=20

and increase only after load testing demonstrates a need for additional concurrency.

Fixed-Size Pool Recommendation

For many production workloads, a fixed-size pool provides the simplest and most predictable behavior.

Configure:

maximumPoolSize=20
minimumIdle=20

or omit minimumIdle entirely so it defaults to maximumPoolSize. HikariCP commonly recommends maintaining a fixed-size pool for responsiveness during demand spikes.

Benefits

  • Faster connection acquisition
  • Predictable performance
  • Reduced connection creation latency
  • Better handling of traffic spikes

When using a small fixed-size pool, there is often little need to aggressively tune:

  • minimumIdle
  • idleTimeout

Instead, simply recycle connections using:

maxLifetime

maxLifetime

Additional Recommendations

Enable TCP Keepalive

One common cause of stale connections is network devices silently dropping inactive TCP sessions.

For PostgreSQL applications, consider enabling TCP keepalive:

tcpKeepAlive=true

tcpKeepAlive=true

The HikariCP project specifically recommends enabling TCP keepalive to prevent rare situations where pools can lose valid connections.

Monitor Connection Usage

Track:

  • Active connections
  • Idle connections
  • Connection acquisition time
  • Pool exhaustion events
  • Database connection counts

These metrics help identify whether pool sizing is appropriate.

Investigate Long-Running Queries

Connection pool problems are often symptoms rather than root causes.

A frequent scenario is:

  1. A query becomes slow.
  2. Connections remain occupied longer.
  3. The pool becomes exhausted.
  4. Applications start timing out.

When analyzing HikariCP issues, always review:

  • Query performance
  • Blocking situations
  • Database resource utilization
  • Application connection handling logic

Sample Production Configuration

spring.datasource.hikari.maximumPoolSize=20

spring.datasource.hikari.minimumIdle=15

spring.datasource.hikari.maxLifetime=1800000

spring.datasource.hikari.idleTimeout=600000

spring.datasource.hikari.connectionTimeout=30000

spring.datasource.hikari.keepaliveTime=60000

spring.datasource.hikari.maximumPoolSize=20
spring.datasource.hikari.minimumIdle=15
spring.datasource.hikari.maxLifetime=1800000
spring.datasource.hikari.idleTimeout=600000
spring.datasource.hikari.connectionTimeout=30000
spring.datasource.hikari.keepaliveTime=60000

This configuration provides a solid starting point for many Azure Database for PostgreSQL workloads and can be adjusted based on application-specific requirements.

a { text-decoration: none; color: #464feb; } tr th, tr td { border: 1px solid #e6e6e6; } tr th { background-color: #f5f5f5; }

Conclusion

HikariCP is extremely efficient when configured appropriately. The goal is not to maximize the number of connections, but rather to maintain a healthy balance between application responsiveness and database resource consumption.

As a general rule:

  1. Use a reasonable maxLifetime (30–60 minutes)
  2. Keep enough idle connections available for traffic spikes
  3. Avoid aggressive idleTimeout values
  4. Size the pool based on workload characteristics, not guesses
  5. Consider fixed-size pools for predictable performance
  6. Monitor connection usage and query performance regularly

By following these practices, applications connecting to Azure Database for PostgreSQL can achieve improved scalability, lower latency, and more reliable connectivity.

References

Connection pooling best practices – Azure Database for PostgreSQL

Performance best practices for using Azure Database for PostgreSQL – Connection Pooling

HikariCP Documentation and Pool Sizing Guidance

  This article was originally published by Microsoft's Azure Database Support Blog. You can find the original article here.