Right-Sizing Connections in YugabyteDB with YSQL Connection Manager (YCM)

Why Connection Counts Matter in YugabyteDB

One of the most common questions when deploying YugabyteDB in production is:

  • How many database connections should each node support?

This becomes especially important when using the YSQL Connection Manager (YCM) and even more critical in stretch clusters where nodes span multiple regions or availability zones.

Because YugabyteDB’s YSQL layer inherits PostgreSQL’s process-per-connection architecture, every backend connection consumes CPU and memory. If connection counts grow too high, CPU context switching and memory overhead can degrade performance, even when queries themselves are simple.

YSQL Connection Manager solves this by allowing many logical client connections to multiplex onto a smaller pool of physical backend connections.

This tip explains:

  • ● how to calculate safe backend connection limits

  • ● how to configure YSQL Connection Manager to enforce those limits

  • ● how logical application connections map to physical backend processes

  • ● how to size backend capacity in multi-region stretch clusters

  • ● how to run a simple demo where 500 logical connections collapse into ~50 backend processes

Logical vs Physical Connections

When applications connect through YCM, the connection they see is not always a dedicated backend process.

Instead, YCM acts as an intermediary:

				
					Application Clients (Logical Connections)
                  │
                  ▼
         YSQL Connection Manager
                  │
                  ▼
YSQL Backend Processes (Physical Connections)
				
			

This architecture allows thousands of client sessions to share a much smaller backend pool.

Connection Type Description
Logical connections Client sessions from apps, services, or connection pools.
Physical connections Actual YSQL backend processes (process-per-connection).

Most applications spend significant time idle waiting on network or application logic, allowing YCM to reuse backend processes efficiently.

Baseline Rule: Connections per vCPU

The standard rule of thumb for YugabyteDB clusters is:

				
					10–15 backend connections per vCPU
				
			
Workload Type Connections per vCPU
Latency-sensitive OLTP ~10
Balanced workloads ~15
Batch / analytical workloads depends on workload

Example:

Node configuration:

				
					16 vCPU node
				
			

Recommended backend capacity:

Mode Backend Connections
Conservative (low latency) 160
Maximum 240

These represent actual backend processes, not application connections.

💡 Key Insight
The 10–15 connections per vCPU rule applies to physical backend processes, not application sessions. With YSQL Connection Manager enabled, thousands of logical client connections can safely share a backend pool sized according to CPU capacity.

Enforcing the Ratio with YCM

Once you calculate your backend capacity, configure YugabyteDB so the database enforces that limit.

Enable YSQL Connection Manager
				
					yugabyted start \
  --tserver_flags="enable_ysql_conn_mgr=true"
				
			

YCM runs inside every TServer.

Limit Backend Connections

Next configure the maximum backend processes:

				
					--ysql_max_connections=240
				
			

This ensures backend connections never exceed CPU capacity.

Allow High Client Concurrency

Now allow many logical client sessions:

				
					--ysql_conn_mgr_max_client_connections=5000
				
			

YCM multiplexes those sessions onto the backend pool.

Example Node Configuration

For a 16-core node:

				
					yugabyted start \
  --tserver_flags="
  enable_ysql_conn_mgr=true,
  ysql_max_connections=240,
  ysql_conn_mgr_max_client_connections=5000
  "
				
			

Result:

Connection Type Limit
Client connections 5000
Backend processes 240

Example Application Scenario

Imagine a Kubernetes deployment:

				
					20 application pods
HikariCP
maxPoolSize = 50
				
			

Maximum client sessions:

				
					20 × 50 = 1000 logical connections
				
			

But backend capacity might be:

				
					240 backend connections per node
				
			

YCM ensures those 1000 client sessions share the backend pool efficiently.

Sizing Calculator for Field Engineers

The following sizing calculator provides a quick reference for determining safe backend connection limits based on node CPU capacity.

vCPU per Node Backend Connections (10 × vCPU) Backend Connections (15 × vCPU) Suggested YCM Client Limit
4 40 60 1000
8 80 120 2000
16 160 240 5000
32 320 480 8000
64 640 960 15000
Practical Recommendation
  • ● Protect backend connections based on CPU.

  • ● Allow large client pools.

  • ● Monitor pinned sessions.

Monitoring Connections

Backend Sessions
				
					SELECT count(*) FROM pg_stat_activity;
				
			

Shows active backend processes.

Prometheus Metrics

More useful for monitoring load:

				
					yb_ysqlserver_active_connection_total
				
			

This metric shows queries actively executing rather than just open sessions.

Memory Considerations

Each PostgreSQL backend process consumes memory.

Typical usage:

				
					10–20 MB per backend
				
			

Example:

				
					240 backends × 15MB ≈ 3.6GB RAM
				
			

This baseline memory usage must be accounted for when sizing YugabyteDB nodes.

However, it’s important to remember that this estimate only applies to idle sessions.

Queries that perform operations such as:

  • ● large joins

  • ● sorting

  • ● aggregation

  • ● hash joins

  • ● large result sets

can consume significantly more memory per backend process.

🧠 Key Insight
The 10–20 MB memory estimate applies to idle backend sessions only. Backends executing complex queries can temporarily consume much more memory, especially during sorts, hash joins, and aggregations. This is another reason why limiting backend connections per node is important.

Monitoring Memory Usage

When investigating memory pressure, it can be useful to identify which backend sessions are consuming the most memory.

A practical way to do this is by examining the VmHWM (High Water Mark) memory metric exposed by YugabyteDB.

If you want to learn how to identify memory-heavy backends, see this YugabyteDB Tip:

This technique helps detect queries whose backend processes are consuming significantly more memory than expected.

Stretch Cluster Example

Connection sizing becomes even more important in multi-region deployments.

A common YugabyteDB architecture spans three regions to provide both fault tolerance and low-latency local access.

Example deployment:

				
					Region A (us-east)
  Node1
  Node2
  Node3

Region B (us-central)
  Node4
  Node5
  Node6

Region C (us-west)
  Node7
  Node8
  Node9
				
			

Assume each node has:

				
					16 vCPU
				
			

Using the recommended guideline:

				
					10–15 backend connections per vCPU
				
			

Each node should support approximately:

				
					160–240 backend connections
				
			
Cluster Backend Capacity
Region Nodes Backend per Node Total Backend Capacity
Region A 3 160–240 480–720
Region B 3 160–240 480–720
Region C 3 160–240 480–720
Total Cluster 9 1440–2160

This represents the maximum safe number of active backend sessions across the entire cluster.

With YSQL Connection Manager enabled, the cluster could still support many thousands of logical application connections, while keeping backend processes within safe CPU limits.

Why YCM Matters More in Multi-Region Clusters

Stretch clusters introduce additional challenges that make connection pooling even more important.

1️⃣ Cross-Region Catalog Access

Each new backend session must initialize system catalogs. If the YB-Master leader resides in another region, connection setup may incur cross-region network latency.

Connection pooling avoids this repeated initialization overhead.

2️⃣ Connection Warmth

YCM keeps backend processes warm and ready, avoiding repeated authentication and catalog initialization.

This reduces latency spikes during traffic bursts.

3️⃣ Session Pinning

Some operations force a session to remain attached to a backend process:

  • TEMP TABLE

  • SET session parameters

  • WITH HOLD cursors

Pinned sessions reduce pooling efficiency and should be monitored in large deployments.

Optional Optimization for Stretch Clusters

To reduce metadata lookup overhead during connection initialization, you can preload additional catalog tables:

				
					--ysql_catalog_preload_additional_tables=true
				
			

This helps reduce latency spikes when connections initialize metadata.

Live Demo: 500 Logical Connections Collapse into ~50 Backend Processes

This demo is designed to make the “logical vs physical” concept obvious in 5 minutes:

  • ● 500 client sessions (logical connections)

  • ● ~50 backend processes (physical connections)

  • ● powered by YSQL Connection Manager (YCM)

You’ll run this on a single node (easy) and validate with pg_stat_activity.

What you’ll see
  • Without YCM
    500 clients ⇒ ~500 backends (you’ll crush CPU/memory quickly)
  • With YCM + backend cap
    500 clients ⇒ ~50 backends (stable + predictable)
Step 0: Start YugabyteDB with YCM and a backend cap

Pick a small backend cap so the multiplexing is obvious:

  • ysql_max_connections=50 → physical backend cap

  • ysql_conn_mgr_max_client_connections=1000 → allow many logical clients

Example (single-node yugabyted):

				
					yugabyted start \
  --tserver_flags="enable_ysql_conn_mgr=true,ysql_max_connections=50,ysql_conn_mgr_max_client_connections=1000"
				
			

If you’re doing this on a real multi-node cluster, apply the same flags to every TServer.

Step 1: Create a tiny workload
				
					CREATE DATABASE ycmdemo;
\c ycmdemo

CREATE TABLE demo_kv (
  k INT PRIMARY KEY,
  v TEXT
);

INSERT INTO demo_kv
SELECT g, repeat('x', 50)
FROM generate_series(1, 10000) g;
				
			
Step 2: Open 500 logical client connections

pgbench (fast + easy)

				
					pgbench -h <host> -p 5433 -U yugabyte -d ycmdemo -c 500 -j 50 -T 60 \
  -f /dev/stdin <<'SQL'
SELECT v FROM demo_kv WHERE k = (random()*10000)::int + 1;
SQL
				
			
  • -c 500500 logical clients

  • -j 50 → run with 50 worker threads (doesn’t change the client count, just execution)

Step 3: Observe the backend process count (physical connections)

Run this while the load is running:

				
					-- Show max physical connections allowed
SHOW max_connections;

-- Total backend processes (physical sessions)
SELECT count(*) AS backend_processes
FROM pg_stat_activity
WHERE datname = 'ycmdemo';

-- Optional: view state breakdown
SELECT state, count(*)
FROM pg_stat_activity
WHERE datname='ycmdemo'
GROUP BY 1
ORDER BY 2 DESC;
				
			
Expected result (with YCM configured)

Even with 500 logical clients, you should see something like:

  • backend_processes hovering around ~50 (or slightly above/below depending on timing and pinned sessions)

Show how many backends are really doing work (not just “connected”)

The pgbench summary shows the number of clients and threads:

				
					transaction type: /dev/stdin
scaling factor: 1
query mode: simple
number of clients: 500.     < -- Logical
number of threads: 50.      < -- Physical
maximum number of tries: 1
duration: 60 s
number of transactions actually processed: 21385
number of failed transactions: 0 (0.000%)
latency average = 1634.750 ms
initial connection time = 4237.385 ms
tps = 305.857219 (without initial connection time)
				
			

Final Thoughts

Proper connection sizing is one of the simplest and most effective ways to improve YugabyteDB performance and stability.

🛡️ Why Connection Limits Protect Both CPU and Memory

Every YSQL connection corresponds to a backend process. Each backend consumes CPU scheduling resources and memory, even when idle.

If backend connections grow unchecked, the database can suffer from:

  • ● Excessive CPU context switching
  • ● Higher latency due to scheduler contention
  • ● Increased memory pressure from idle backend processes
  • ● Greater risk of OOM events when heavy queries run

By limiting backend connections to roughly 10–15 per vCPU and using YSQL Connection Manager to multiplex client sessions, YugabyteDB clusters maintain predictable CPU scheduling, stable memory usage, and consistent query latency, even when supporting thousands of application connections.

Key takeaways:

  • ● Limit backend connections to 10–15 per vCPU

  • ● Use YSQL Connection Manager to multiplex client sessions

  • ● Allow large logical connection pools

  • ● Monitor pinned sessions

  • ● Account for backend memory usage

When configured correctly, YugabyteDB clusters can support thousands of application connections while maintaining predictable latency and CPU usage.

Have Fun!