MySQL

How to Fix "Too Many Connections" Error in MySQL Production

4 min read by DebuggedIt

Quick answer

Your application starts failing to connect to MySQL during peak traffic, and the server itself is rejecting new connections outright. This means every...

Your application starts failing to connect to MySQL during peak traffic, and the server itself is rejecting new connections outright. This means every connection slot MySQL was configured to allow is already in use β€” either from genuinely high legitimate load, or from connections that were opened and never properly closed.

The Problem

New connection attempts fail with a clear, specific error:

ERROR 1040 (HY000): Too many connections

Existing connections keep working, but anything new β€” a fresh request, a new worker process, a monitoring check β€” can't get through:

$ mysql -u app_user -p
ERROR 1040 (HY000): Too many connections

Even root can get locked out unless a reserved connection slot is configured, which makes debugging the live server harder in the middle of the incident.

Connection pool exhaustion max_connections: 151 (MySQL default) 151 connections open (many idle/leaked, some sleeping for hours) Fix: find leaked connections first, THEN consider raising the limit

Why It Happens

MySQL enforces a hard cap on simultaneous connections via max_connections, defaulting to 151 on most installs β€” a number that's often far too low for a busy production service, but raising it blindly can also mask a real problem. This error has two distinct root causes that need different fixes:

  • Genuinely high legitimate concurrency β€” enough real simultaneous users or worker processes to actually need more than the configured limit.
  • Connection leaks β€” application code opening database connections and never closing them (missing cleanup in an error path, a connection pool misconfigured with too high a max size, ORM sessions not being properly disposed), so the count climbs over time even without proportionally more real traffic.

Distinguishing between these matters, because raising max_connections alone fixes the first case but only delays the second β€” a leak will eventually exhaust whatever limit you set.

The Fix

First, check the current limit and how many connections are actually in use right now:

SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Max_used_connections';

Look at what those connections are actually doing β€” a large number sitting in Sleep state for a long time is a strong signal of leaked or poorly pooled connections rather than active load:

SELECT id, user, host, db, command, time, state
FROM information_schema.processlist
ORDER BY time DESC
LIMIT 20;
+----+----------+-----------+------+---------+------+-------+
| id | user     | host      | db   | command | time | state |
+----+----------+-----------+------+---------+------+-------+
| 42 | app_user | 10.0.0.5  | app  | Sleep   | 7211 |       |
| 43 | app_user | 10.0.0.5  | app  | Sleep   | 7198 |       |
+----+----------+-----------+------+---------+------+-------+

A large number of connections sleeping for thousands of seconds is your application's connection pool holding connections it isn't using β€” check its configured pool size and idle timeout:

# Example: reasonable connection pool settings
max_pool_size: 20
idle_timeout: 300  # close connections idle longer than 5 minutes
max_lifetime: 1800 # recycle connections after 30 minutes regardless

If the load is genuinely legitimate and you've confirmed there's no leak, raise the limit β€” check your available RAM first, since each connection consumes memory:

SET GLOBAL max_connections = 300;

Make it persistent in my.cnf so it survives a restart:

[mysqld]
max_connections = 300

Reserve a slot for administrative access so you're never locked out during an incident:

[mysqld]
max_connections = 300
extra_max_connections = 5

Still Not Working?

If connections keep climbing back to the limit even after raising it and confirming pool settings look reasonable, check whether a specific application server or script is the actual source by grouping the process list by host:

SELECT host, COUNT(*) as connection_count
FROM information_schema.processlist
GROUP BY host
ORDER BY connection_count DESC;

A single host with a disproportionate share of connections points at one specific misbehaving service or deployment, rather than distributed legitimate load β€” worth investigating that host's connection pooling configuration and recent deploys directly before raising limits any further.