Understanding ysql_conn_mgr_reserve_internal_conns and Connection Queuing

When using the YugabyteDB YSQL Connection Manager, you may come across this setting: ysql_conn_mgr_reserve_internal_conns

At first glance, the name can be a little confusing.

  • ● Does Connection Manager need these reserved connections for itself?
  • ● What happens if the value is 0?
  • ● And if all PostgreSQL backends are busy, how does Connection Manager service clients waiting in its queue?

The answers are useful for understanding both YSQL Connection Manager behavior and how to think about connection sizing.

The Short Answer

ysql_conn_mgr_reserve_internal_conns reserves a portion of ysql_max_connections so those PostgreSQL backend connections cannot be consumed by Connection Manager.

Those reserved connections remain available for operations that need to connect directly to PostgreSQL rather than through Connection Manager.

These reserved connections can be used by operations such as:

  • ● Index backfill operations
  • ● YugabyteDB Anywhere (YBA) operations
  • ● Operations that connect using Unix domain sockets
  • ● Other internal or Day-2 administrative activity

The setting is therefore primarily about protecting capacity for direct/internal connections.

It is not a pool of connections that Connection Manager itself requires in order to process its wait queue.

How the Connection Limits Relate

At a high level:

ysql_max_connections
|
+-- Connections available to YSQL Connection Manager
|
+-- Connections reserved for direct/internal operations

Conceptually:

Connections available to Connection Manager = ysql_max_connectionsysql_conn_mgr_reserve_internal_conns

For example:

Setting Value
ysql_max_connections 60
ysql_conn_mgr_reserve_internal_conns 5
Maximum backends available to Connection Manager 55
Reserved for direct/internal connections 5

The value 5 here is simply an example to illustrate the behavior. It is not a universal recommended setting.

What Happens When the Reserve Is 0?

Consider:

				
					ysql_max_connections = 60
ysql_conn_mgr_reserve_internal_conns = 0
				
			

Connection Manager can create up to all 60 PostgreSQL backends.

Now suppose the application has 90 clients actively trying to execute work.

Conceptually:

  90 application clients
|
v
+-------------------------+
| YSQL Connection Manager |
+-------------------------+
|
+---- 60 clients using PostgreSQL backends
|
+---- 30 clients waiting
Resource Count State
Application clients 90 Connected to Connection Manager
PostgreSQL backends 60 Busy servicing clients
Waiting clients 30 Waiting for a backend
Reserved internal connections 0 No capacity explicitly protected from Connection Manager

As soon as one of the active sessions finishes its work and its PostgreSQL backend becomes idle, Connection Manager can assign that backend to a waiting client.

Does Connection Manager Need a Free PostgreSQL Connection to Manage the Queue?

No.

This is an important distinction.

The reserved connections are not required by Connection Manager to maintain its client queue.

Connection Manager can have considerably more client connections than physical PostgreSQL backends.

Its job is to multiplex those logical client connections over a smaller number of physical backend connections.

Think of it this way:

    CLIENT CONNECTIONS
1
2
3
4
5
.
.
.
90
|
v
+-----------------------+
| YSQL Connection |
| Manager |
| |
| Active + Wait Queue |
+-----------------------+
|
v
+-----------------------+
| PostgreSQL Backends |
| |
| 1 2 3 ... 60 |
+-----------------------+

The clients waiting inside Connection Manager do not each consume their own PostgreSQL backend.

That is one of the main reasons to use Connection Manager.

💡 Related YugabyteDB Tip
Want to dig deeper into the difference between logical client connections and physical backend connections? See:
YSQL Connection Manager: Why Active Queries Still Need Backend Connections

How Expensive Is Moving a Client Out of the Queue?

Another useful question is whether a heavily populated wait queue introduces substantial Connection Manager overhead.

For example:

				
					60 PostgreSQL backends busy
60 additional clients waiting
				
			

When a backend becomes idle, how long does Connection Manager need to assign it to another client?

According to the YugabyteDB engineering discussion that prompted this tip, the multiplexing cost is measured in milliseconds and was described as less than 10 ms.

Internally, the operation is relatively lightweight. Connection Manager tracks idle backends and, when reassigning one, performs the required session setup, including applying relevant GUC state.

That means the dominant wait experienced by a queued client is normally the time spent waiting for an existing query to release a backend … not the Connection Manager handoff itself.

For example:

				
					Query occupying backend:       250 ms
Connection Manager handoff:    <10 ms
                               -------
Client wait dominated by:      Query execution
				
			

This distinction becomes important when troubleshooting latency.

What Changes When You Reserve Connections?

Now consider:

				
					ysql_max_connections = 60
ysql_conn_mgr_reserve_internal_conns = 5
				
			

Connection Manager can now use up to 55 PostgreSQL backends, while 5 connections remain outside its pool for direct/internal operations.

If the same 90 application clients are trying to execute work:

   90 application clients
|
v
+-------------------------+
| YSQL Connection Manager |
+-------------------------+
|
+---- 55 PostgreSQL backends
|
+---- 35 clients waiting


5 application connections
          |
           +---- reserved for direct/internal operations
Scenario CM Backends Waiting Clients Reserved
Reserve = 0 60 30 0
Reserve = 5 55 35 5

Notice the tradeoff.

Increasing ysql_conn_mgr_reserve_internal_conns does not create additional database capacity.

It moves some of the existing PostgreSQL backend capacity out of the Connection Manager pool and protects it for direct/internal use.

As a result, fewer application requests can execute simultaneously and more may wait in the Connection Manager queue.

⚠️ Don’t Treat the Reserve Setting as a Performance Knob

It can be tempting to increase ysql_conn_mgr_reserve_internal_conns simply to reduce the number of application backends executing simultaneously.

That may reduce concurrency, but that is not the primary purpose of the setting.

Its purpose is to protect PostgreSQL backend capacity required outside Connection Manager.

If the database performs better with fewer simultaneous PostgreSQL backends, that can certainly be an important workload-tuning observation… but it should be treated separately from the need to reserve connections for internal activity.

More Connections Can Actually Make Things Slower

This is perhaps the most interesting part of the discussion.

Suppose a node has limited CPU capacity.

Allowing more and more queries to execute simultaneously does not necessarily increase throughput.

Eventually, those queries start competing for the same CPU resources.

In one customer use case, reducing concurrency from approximately 15 active clients per vCPU to about 10 active clients per vCPU actually improved performance.

This does not mean 10 connections per vCPU is a universal YugabyteDB sizing recommendation.

The correct level of concurrency is workload-dependent.

💡 Related YugabyteDB Tip
For a deeper look at sizing physical backend connections based on CPU capacity, see:
Right-Sizing Connections in YugabyteDB with YSQL Connection Manager (YCM)

But it illustrates an important principle:

  • More active database connections ≠ More database throughput

Sometimes allowing Connection Manager to queue work is healthier than forcing every connected client to execute simultaneously.

Connection Manager Changes the Connection-Sizing Conversation

Without connection pooling, it is natural to think:

  • 100 clients = 100 PostgreSQL backends

With YSQL Connection Manager:

          100 clients
|
v
Connection Manager
|
v
Smaller pool of PostgreSQL backends

This separation lets the application maintain many client connections while YugabyteDB controls how many physical PostgreSQL backends are executing work.

For example:

    100 client connections
|
v
+--------------------------+
| YSQL Connection Manager |
+--------------------------+
|
v
40 PostgreSQL backends

The remaining clients can wait rather than forcing the database to run 100 requests simultaneously.

For many workloads, that is exactly what you want.

Troubleshooting a Backed-Up Connection Manager

Suppose you observe:

				
					60 PostgreSQL backends active
60 clients waiting
				
			

and application latency becomes very high.

It is easy to conclude:

  • Connection Manager is slow.

But that may not be what is happening.

Ask these questions instead:

Question Why It Matters
How long are the active queries running? Waiting clients cannot proceed until a backend becomes idle.
Is the node CPU saturated? Adding more simultaneously executing backends may make contention worse.
Would additional CPU capacity help? Persistent concurrency pressure may indicate the workload needs more compute rather than more connections.
Is ysql_max_connections appropriate? Too few backends can cause unnecessary queuing, while too many can increase resource contention.
Are connections protected for internal operations? The reserve prevents Connection Manager from consuming backend capacity needed by direct/internal operations.

The wait queue is therefore not automatically evidence of a Connection Manager problem.

It may simply be exposing the database’s actual concurrency limit.

Think of It This Way

Think of Connection Manager like a restaurant with 60 tables.

You might have:

				
					90 customers
60 tables
				
			

Sixty customers can eat while thirty wait.

When someone finishes:

  table becomes free
|
v
next customer is seated

You don’t need 90 tables simply because 90 customers arrived.

And adding tables when the kitchen is already overloaded may actually make service worse.

Now imagine that a few tables need to remain available for restaurant staff performing important operational tasks.

That is conceptually what ysql_conn_mgr_reserve_internal_conns does.

It prevents Connection Manager from consuming every available PostgreSQL backend connection.

Key Takeaways

  • ysql_max_connections controls the total PostgreSQL backend connection capacity.
  • ysql_conn_mgr_reserve_internal_conns removes a number of those connections from the pool available to YSQL Connection Manager.
  • ● The reserved connections are intended for direct/internal operations such as index backfills and certain YBA operations.
  • ● Setting the reserve to 0 allows Connection Manager to potentially use the entire ysql_max_connections capacity.
  • ● Clients beyond the available backend capacity can remain connected to Connection Manager and wait for a backend.
  • ● Connection Manager does not need a reserved PostgreSQL connection simply to maintain or service its wait queue.
  • ● YugabyteDB engineering described the backend multiplexing/handoff cost as being in the millisecond range and less than 10 ms in the scenario discussed.
  • ● Increasing the reserve means fewer PostgreSQL backends are available to application traffic and therefore potentially more queued clients.
  • ● A large queue does not necessarily mean Connection Manager itself is the bottleneck. Query duration and CPU saturation may be the dominant factors.
  • ● More simultaneously active PostgreSQL connections do not automatically mean more throughput.
  • ● If performance collapses under high concurrency, increasing connection limits may make things worse. Investigate CPU capacity, query execution time, and the appropriate level of backend concurrency.

Final Takeaway

The most important thing to remember is that YSQL Connection Manager separates:

  • How many clients can connect

From:

  • How many PostgreSQL backends should execute work simultaneously

That separation is a feature.

ysql_conn_mgr_reserve_internal_conns adds another piece to the equation by ensuring that some PostgreSQL backend capacity can remain outside the Connection Manager pool for operations that need to connect directly.

So when you see clients waiting in Connection Manager, don’t immediately assume the answer is more connections.

Sometimes the queue is doing exactly what it was designed to do:

  • allowing many clients to connect while limiting the amount of work executing concurrently against the database.

Have Fun!

The new Gameway gaming lounge just opened at Pittsburgh International Airport! 🎮✈️

Of course it opens right as I’m getting ready to move to Dallas and won’t be flying out of PIT anymore. Figures! 😂

But wait… good news… there are two Gameways at DFW! Looks like I’m not losing my airport gaming fix after all. 😎🎮