The Myth of Large Connection Pools
A common intuition among developers is that larger connection pools increase database throughput. If you have 50 worker threads in your application, you might configure your HikariCP maximumPoolSize to 50. In reality, this configuration will decrease your database's performance under load.
Why Small Pools are Faster
PostgreSQL (and most relational databases) process queries using CPU cores. If a database server has 4 CPU cores, it can only execute 4 queries simultaneously in parallel. Any connections beyond that are essentially put in a queue, waiting for a core to become available.
When you configure a pool of 100 active connections against a 4-core database, the OS spends a massive amount of time context-switching between threads, thrashing CPU caches, and fighting for locks, rather than actually doing the work of executing the query.
The Optimal Formula
The generally accepted formula for optimal connection pool sizing (popularized by PostgreSQL experts and the HikariCP wiki) is:
connections = ((core_count * 2) + effective_spindle_count) - core_count: The number of CPU cores physically available to the database instance.
- effective_spindle_count: Hard disks have physical spindles that can seek data independently. For modern SSDs (which lack spindles but have high concurrency), this is usually treated as 1.
Handling Multiple Application Instances
If you run your application in Kubernetes with 10 pods, and your optimal database connection limit is 25, you cannot set maximumPoolSize=25 in your application code. That would result in 250 total connections.
You must divide the total optimal connections by your instance count (e.g., 25 / 10 = 2.5). Each pod should have a pool size of 2 or 3. If this number becomes too small to be practical (e.g., < 2), you must use a connection multiplexer like PgBouncer or AWS RDS Proxy between your application and the database.