Your Client Connection Pool isn’t the Problem

What happens to your database when Kubernetes multiplies your client-side pools?
Manav Kumar

A client-side connection pool bounds one application process. An autoscaler multiplies those processes. Together they make your database connection count a function of pod count rather than query volume – and the ceiling arrives sooner than you’d expect.

In this blog, we share how one customer faced 1,920 required connections against a cluster sized for 360 days before go-live. More hardware or smaller pools was not the solution. Discover how YSQL Connection Manager resolved the issue with a single setting and no application changes.

1,920 Connections Required, 360 Available

A customer shared a problem that looked simple on a whiteboard, but proved expensive in production.

They were putting two services live against YugabyteDB. Both would autoscale under load. Multiply max pods by max pool size; if both services peaked together, the apps would have needed 1,920 connections. In reality, the cluster could serve about 360.

The customer’s first instinct was common: just add nodes, buy more vCPUs, close the gap with hardware. That works, but it would have increased costs just to hold connections that were mostly idle. They also did not want to change the application code. The services were ready to go live with the existing Hikari and Horizontal Pod Autoscale (HPA) settings, and rewriting pools or wiring in a new proxy tier was not on the table.

Nothing was misconfigured. Kubernetes would scale as instructed, and HikariCP would hold exactly the pools it was told to hold. YugabyteDB YSQL would create one backend process per connection, the same process-per-connection model it inherits from PostgreSQL. Each layer was doing its job, but stacked together, they let the application demand far more connections than the cluster could ever create.

The customer needed a fix that preserved the app config, avoided a large hardware bill, and still allowed them to go live. They enabled YugabyteDB’s newly released YSQL Connection Manager and kept the application setup. Here’s how!

What They Built

Both of the customer’s services ran on Kubernetes, each starting with three pods, with HPA allowed to scale to 64 under load. Behind them sat a three-node YugabyteDB cluster with eight vCPUs per node.

Each service used HikariCP. Service one had minIdle 3 and maxPoolSize 10, so at 64 pods, that is 640 connections. Service two had minIdle 20 and maxPoolSize 20, so at 64 pods, that is 1,280. If both hit max together, the total is 1,920.

A fixed-size pool is a reasonable choice. It keeps connection setup off the hot path and makes per-pod usage predictable. It also means each pod can scale to its maximum pool size and retain those connections for its lifetime, whether busy or idle.

Each held connection is a dedicated YSQL backend. Hikari exposes open sockets within the JVM; it is not a cluster-wide gate. Worst-case connection count tracks pod count × pool size, not query volume.

Hitting The Ceiling: Why a Backend is Expensive

YSQL inherits PostgreSQL’s process-per-connection model. Every connection gets its own backend process, with its own memory, caches, and scheduler share. That is the reason the connection count gets expensive quickly.

Sizing guidance is about 15 connections per vCPU, so this cluster had about 360 backends in total (15 × 8 × 3):

  • At baseline, three pods per service, each holding max pools, is about 90 connections (which is comfortable).
  • At around 12 pods per service, they reach the 360 ceiling
  • At 32 pods per service, they are at 960, about 2.7× over
  •  At 64 pods, they are at 1,920, about 5.3× over

This means they would cross capacity long before HPA reached sixty-four.

Why Adding Nodes Was the Wrong Move

Serving 1,920 backends at 15 per vCPU requires about 128 vCPUs, roughly a 5× increase over the 24 vCPUs they already had. Those cores would mostly hold idle connections rather than run queries. Understandably, the customer did not want that cost just to go live.

Production already showed the pattern: total YSQL connections in the mid-hundreds, active connections near zero. Growing the cluster until 1,920 physical backends fit would have bought reservations, not query capacity.

Tuning Hikari Was Not Enough

Hikari was doing its job. It bounds one JVM, cannot see the other pods, and there is no cluster-wide budget across client pools.

Smaller pools help, but still do not fix HPA.

Hand-splitting 360 backends across 64 pods cripples the baseline, and it would have required changing the application config right before launch. No single per-pod number works at both ends of the range, because the range is the problem.

What Fixed It

The Yugabyte team recommended enabling YSQL Connection Manager with one YB-TServer setting:

enable_ysql_conn_mgr=true

Client connections became logical connections, multiplexed onto fewer physical YSQL backends.

At full planned peak, 1,920 logical connections against 360 physical connections is about 5:1, which the connection manager can comfortably handle. It creates lightweight threads for each logical connection and efficiently multiplexes them over physical connections. This can easily push the boundaries to handle traffic at a 20:1 ratio.

The customer started with about 960 client connections through the pooler, with room to grow later. That 960 is a Connection Manager’s logical client connection, which has a default limit of 10,000, not a new physical-backend ceiling. The cluster stayed on the original 8-vCPU nodes. Application code and pool settings stayed as planned for go-live, and no large hardware expansion was required.

Ratios vary with workload, and long transactions and sticky session features reduce multiplexing. Despite that, this solution was far cheaper than sizing for 1,920 dedicated backends.

How YSQL Connection Manager Works

YSQL Connection Manager is a modified Odyssey build within YugabyteDB. It runs in transaction pooling mode with wire protocol changes, so more PostgreSQL features work transparently than with a typical external transaction pooler.

When enabled, clients typically continue using the familiar YSQL port (5433), while the backend PostgreSQL process is moved aside. Apps still see a normal PostgreSQL-compatible endpoint. This was important in this case, as the team did not want application-side connection string or pooling rewrites before launch.

The model splits into two:

  • Logical client connections are cheap.
  • Physical YSQL backends are expensive, pooled, and shared

Hikari cannot do that split. It never sits in the query path, so its pool entries are reservations rather than shared cluster slots. External poolers can also multiplex, at their own operational cost.

Because YSQL Connection Manager sits inside YugabyteDB, there is no separate proxy tier to run, authentication stays on the database path, and more session-oriented features work without redesigning the app for pooling.

There is one caveat: Some session features still pin a backend for the session (sticky connections). Design for multiplexing where you can, and measure stickiness where you cannot.

What the Customer Kept

HikariCP stayed in the apps. HPA kept 3-to-64. Teams did not hand-split a global budget across services, did not change application code to go live, and did not insert a separate proxy into the request path. They also avoided the cost of sizing the cluster for thousands of mostly idle backends.

That is the correct outcome. Hikari keeps connections warm inside a pod. Connection Manager binds physical backends across all application pods. You want both, but only one belongs in the application.

The One-Minute Check and Next Steps

If you run autoscaling pods against a database, take a minute to check your setup.

For each service, multiply max replicas × max pool size, add the results, and compare the sum to the backends your cluster is sized for (~15 × vCPUs × nodes).

If the first number is larger, you have the same problem as our customer, and you feel the impact on your busiest day. You do not have to resize the cluster or retune your pools to support the peak number of connections. Enabling YSQL Connection Manager on the YugabyteDB cluster would fix this.

Further reading:

To find out more about PostgreSQL connection management challenges and discover how YSQL Connection Manager provides seamless session-state management at scale, check out this recent blog on the General Availability of YSQL Connection Manager in YugabyteDB 2026.1.1, YugabyteDB Anywhere, and YugabyteDB Aeon.

Manav Kumar

Related Posts

Explore Distributed SQL and YugabyteDB in Depth

Discover the future of data management.
Learn at Yugabyte University
Get Started
Browse Yugabyte Docs
Explore docs
PostgreSQL For Cloud Native World
Read for Free