PDOException: SQLSTATE[HY000] [1040] Too many connections
ID: php/too-many-connections
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 83 | active | — | — | — |
Root Cause
MySQL error 1040 occurs when the number of active connections exceeds the server's max_connections limit (default 151). In PHP applications this is commonly caused by: not closing database connections in long-running scripts, opening a new connection on every request without connection pooling, persistent connections accumulating beyond the limit, or multiple worker processes each holding their own connection. The fix involves both application-level connection management and MySQL server tuning.
genericWorkarounds
-
90% success Implement a singleton or shared database connection pattern and explicitly close connections after use
Ensure each PHP request uses a single database connection instead of opening multiple. Use a dependency injection container or singleton pattern for the PDO instance. In long-running scripts or queue workers, explicitly call $pdo = null to close the connection when database work is complete. In frameworks like Laravel, call DB::disconnect() after processing each job in a queue worker. Verify connections are properly released by monitoring with 'SHOW PROCESSLIST' during load testing.
-
88% success Tune max_connections relative to PHP-FPM worker count and add a connection proxy like ProxySQL
Set MySQL max_connections to at least (number of PHP-FPM workers) + (number of other clients) + 10 (reserved for admin). Check current usage with 'SHOW STATUS LIKE "Max_used_connections"'. For high-traffic applications, deploy ProxySQL or MySQL Router as a connection pooler between PHP and MySQL. ProxySQL multiplexes hundreds of application connections onto a smaller pool of actual MySQL connections, dramatically reducing server-side resource usage. Configure with: 'mysql_variables: {max_connections: 500}' in ProxySQL and keep MySQL max_connections at a safe level. -
85% success Identify and terminate leaked connections, then fix the application code causing the leak
Run 'SHOW FULL PROCESSLIST' to see all active connections and identify which application or user is consuming the most. Kill idle connections with 'KILL <process_id>'. Set wait_timeout and interactive_timeout in MySQL (e.g., 'SET GLOBAL wait_timeout = 300') to automatically close idle connections after 5 minutes. Then trace the leak in PHP: look for database connections created inside loops, connections in __construct() without corresponding cleanup, and PDO instances stored in static variables that prevent garbage collection. In Laravel, check for DB::connection() calls that create new connections instead of reusing the default.
Dead Ends
Common approaches that don't work:
-
Simply increasing max_connections in MySQL to a very high value like 10000
78% fail
Each MySQL connection consumes memory (approximately 10-20MB per thread). Setting max_connections extremely high without increasing available RAM causes MySQL to run out of memory and crash or trigger the OOM killer. This trades a connection limit error for a far worse total database outage. The underlying connection leak or mismanagement remains unfixed.
-
Adding sleep() and retry loops around the database connection attempt
82% fail
If connections are leaking, retrying just adds more connections to the pool. Each retry attempt from each PHP process compounds the problem. Under load, retry storms accelerate exhaustion rather than relieving it. The application stalls while sleeping, degrading user experience without solving the root cause.
-
Switching to persistent connections (PDO::ATTR_PERSISTENT) without understanding the implications
70% fail
Persistent connections survive between requests and are reused per PHP-FPM worker. However, if the worker pool size exceeds max_connections, the same exhaustion occurs. Persistent connections also retain transaction state, lock state, and session variables from previous requests, causing subtle data corruption or deadlocks. Without careful pool sizing this makes the problem worse.