Skip to main content

How to Size the MySql.Data Connection Pool

· 5 min read
Jagdish Kumawat
Founder @ Dewiride

Maximum Pool Size defaults to 100, and MySQL's max_connections to 151. So two copies of an app can ask for more than the server allows, and more requests than the pool holds can end the whole process. Here's how I picked a number, from measurements.

Step 1: See How Many You Use​

Send a burst at your API, then ask MySQL. These are 200 requests, 50 at a time:

Terminal
seq 200 | xargs -P 50 -I{} curl -s -o /dev/null -w "%{http_code}\n" "http://localhost:5190/api/v1/products?pageSize=100" | sort | uniq -c
mysql>
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
Output
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_connected | 51 |
+-------------------+-------+
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| Max_used_connections | 51 |
+----------------------+-------+

Fifty requests at once opened 50 connections, plus my own session. A pool grows to meet the demand, up to its limit, so it tells you how many requests overlapped, not how many you needed.

Step 2: Try Different Sizes​

First, make sure a small pool can't hurt you: above its limit, this driver blocks threads, and that can crash the process. With a concurrency limit in front of the pool, I sent 600 requests, 150 at a time:

Maximum Pool SizeResultTimeConnections in MySQL
5All 2002.34 s6
25All 2002.11 s26
100All 2002.13 s101

The burst of 600 requests answering 200 for all of them at each pool size, with the time and the connection count for 5, 25 and 100.

A bigger pool wasn't faster. These queries take about a millisecond, so a few connections keep up, and my test machine ran out of other things first. A pool of 100 only took up more of the server's connections. Your numbers depend on how long your queries take, so run this against your busiest endpoint, with realistic data.

Step 3: Do the Sum​

The total has to stay below max_connections, which also has to cover everything else that connects:

copies of the app × pools per copy × Maximum Pool Size < max_connections

Count the pools. There's one per connection string, and there's a second one you might not expect: Oracle's readiness check connects without a database, so it counts as a different string. I saw both while a burst ran against each:

mysql>
SELECT PROCESSLIST_DB AS db, COUNT(*) AS connections
FROM performance_schema.threads
WHERE PROCESSLIST_USER = 'inventory_app'
GROUP BY PROCESSLIST_DB;
Output
+-----------+-------------+
| db | connections |
+-----------+-------------+
| NULL | 10 |
| inventory | 10 |
+-----------+-------------+

It normally stays at one or two connections, because probes come one at a time. But it can grow, so count it at the worst case.

With a default max_connections of 151 and a pool of 25, three copies come to 3 × 2 × 25 = 150. That's the most you could run there, and a pool of 100 fits only if you can raise the limit.

Step 4: Set It​

Connection string
…;Maximum Pool Size=25

Then watch Max_used_connections in production. How to See How Many Connections MySQL Has Now and at Its Peak shows how. If it never gets near your limit, you could go lower. If requests queue, find out why they're slow before you raise it.

Common Mistakes​

MistakeWhat happensDo this instead
Raising the pool to handle a burstAbove it, the crash moves up with itLimit requests to the size of the pool
Forgetting the copies of your appThe server runs out firstMultiply
Forgetting a limit on the accountmax_user_connections errorsSize them together
Setting Minimum Pool Size high to be safeIdle connections, held for everKnow what it does

Troubleshooting​

SymptomLikely causeFix
Too many connectionsThe sum is over max_connectionsThe fix
Timeout expired … from the poolRequests wait inside the driverThe fix
Unhandled exception under loadRequests above the poolThe fix

Conclusion​

A bigger pool isn't a faster one, once requests can't overrun it. Measure, count the copies and the second pool, and keep the total under max_connections.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.