Introduction

PostgreSQL and MySQL have a maximum number of concurrent connections defined by the max_connections parameter. When this limit is reached, new connection attempts are rejected. In RDS, the default max_connections is based on instance class, and hitting this limit means your application can't connect to the database.

Symptoms

For PostgreSQL:

bash
FATAL: remaining connection slots are reserved for non-replication superuser connections

Or:

bash
FATAL: sorry, too many clients already

For MySQL:

bash
ERROR 1040 (HY000): Too many connections

Application logs:

bash
org.postgresql.util.PSQLException: FATAL: sorry, too many clients already
java.sql.SQLTransientConnectionException: HikariPool - Connection is not available

Common Causes

  1. 1.Connection leaks - Application doesn't close connections properly
  2. 2.Insufficient pooling - Each request opens a new connection
  3. 3.Long-running transactions - Connections held for extended periods
  4. 4.Instance class limits - Default max_connections too low for workload
  5. 5.Zombie connections - Aborted connections not cleaned up
  6. 6.Connection storms - Sudden spike in concurrent requests
  7. 7.Connection timeout misconfiguration - Connections held while waiting

Step-by-Step Fix

  1. 1.Check logs for specific error messages
  2. 2.Verify configuration settings
  3. 3.Test network connectivity
  4. 4.Review recent changes
  5. 5.Apply corrective action
  6. 6.Verify the fix

Step 1: Check Current Connection Count

For PostgreSQL:

sql
SELECT count(*) FROM pg_stat_activity;
SELECT max_conn, used, res_for_super, max_conn - used - res_for_super 
FROM pg_settings max_conn, (SELECT count(*) used FROM pg_stat_activity) s,
     (SELECT setting::int res_for_super FROM pg_settings WHERE name='superuser_reserved_connections') r;

For MySQL:

sql
SHOW STATUS LIKE 'Threads_connected';
SHOW VARIABLES LIKE 'max_connections';
SHOW PROCESSLIST;

Step 2: Identify What's Using Connections

PostgreSQL - Find top connection sources:

sql
SELECT client_addr, usename, application_name, state, count(*)
FROM pg_stat_activity
GROUP BY client_addr, usename, application_name, state
ORDER BY count(*) DESC;

Find long-idle connections:

sql
SELECT pid, usename, application_name, client_addr, state, 
       now() - state_change AS idle_duration
FROM pg_stat_activity
WHERE state = 'idle'
ORDER BY idle_duration DESC;

MySQL - Find connection sources:

sql
SELECT USER, HOST, DB, COMMAND, TIME, STATE, INFO
FROM INFORMATION_SCHEMA.PROCESSLIST
ORDER BY TIME DESC;

Step 3: Kill Idle or Problem Connections

PostgreSQL:

```sql -- Terminate specific connection SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid = 12345;

-- Terminate all idle connections older than 10 minutes SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle' AND query_start < now() - interval '10 minutes'; ```

MySQL:

```sql -- Kill specific connection KILL CONNECTION 12345;

-- Find and kill long-running queries SELECT CONCAT('KILL ', id, ';') FROM INFORMATION_SCHEMA.PROCESSLIST WHERE TIME > 300 AND COMMAND != 'Sleep'; ```

Step 4: Check for Connection Leaks

Application-level causes:

```python # BAD: Connection leak def get_user(user_id): conn = get_db_connection() cursor = conn.cursor() cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) return cursor.fetchone() # conn.close() is never called!

# GOOD: Using context manager def get_user(user_id): with get_db_connection() as conn: with conn.cursor() as cursor: cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) return cursor.fetchone() ```

Enable connection tracking in your application to find leaks:

```python import traceback import weakref

connections = weakref.WeakSet()

def get_db_connection(): conn = create_connection() connections.add(conn) print(f"Connection created. Stack:\n{''.join(traceback.format_stack())}") return conn ```

Step 5: Implement Connection Pooling

Use a connection pooler like PgBouncer or ProxySQL:

For RDS, enable RDS Proxy:

bash
aws rds create-db-proxy \
  --db-proxy-name my-proxy \
  --engine-family POSTGRESQL \
  --auth AuthScheme=SECRETS,SecretArn=arn:aws:secretsmanager:region:account:secret:my-secret \
  --role-arn arn:aws:iam::account:role/rds-proxy-role \
  --vpc-subnet-ids subnet-1 subnet-2 \
  --vpc-security-group-ids sg-1

Or use application-level pooling (HikariCP, pgx pool):

yaml
# application.yml for HikariCP
spring:
  datasource:
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      idle-timeout: 300000
      connection-timeout: 30000
      max-lifetime: 1200000

Step 6: Increase max_connections (If Needed)

Check current limit:

bash
aws rds describe-db-instances --db-instance-identifier my-db \
  --query 'DBInstances[*].[DBInstanceClass,AllocatedStorage]'

Default max_connections by instance class (PostgreSQL):

Instance Classmax_connections
db.t3.micro87
db.t3.small192
db.t3.medium412
db.r5.large850
db.r5.xlarge1700

To modify:

bash
aws rds modify-db-parameter-group \
  --db-parameter-group-name my-param-group \
  --parameters "ParameterName=max_connections,ParameterValue=500,ApplyMethod=pending-reboot"

Then reboot the instance:

bash
aws rds reboot-db-instance --db-instance-identifier my-db

Warning: Increasing max_connections without increasing instance size may cause memory exhaustion.

Step 7: Set Up Connection Monitoring

CloudWatch metric for connection count:

bash
aws cloudwatch put-metric-alarm \
  --alarm-name "rds-connections-high" \
  --metric-name DatabaseConnections \
  --namespace AWS/RDS \
  --dimensions DBInstanceIdentifier=my-db \
  --statistic Average \
  --period 300 \
  --threshold 400 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2 \
  --alarm-actions arn:aws:sns:region:account:alerts

Verification

```bash # Check connection count aws cloudwatch get-metric-statistics \ --namespace AWS/RDS \ --metric-name DatabaseConnections \ --dimensions DBInstanceIdentifier=my-db \ --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%S) \ --end-time $(date -u +%Y-%m-%dT%H:%M:%S) \ --period 300 \ --statistics Average,Maximum

# Should show connections well below max_connections ```

  • [Fix AWS RDS CPU Utilization High](/articles/fix-aws-rds-cpu-utilization-high)
  • [Fix AWS RDS Storage Full](/articles/fix-aws-rds-storage-full)
  • [Fix AWS RDS Slow Query Performance](/articles/fix-aws-rds-slow-query-performance)
  • [AWS troubleshooting: Fix IAM Permission Denied - Complete Tro](fix-iam-permission-denied)
  • [AWS cloud troubleshooting: AWS ACM Certificate Pending Validation Because the](aws-acm-certificate-pending-validation-wrong-route53-zone)
  • [AWS cloud troubleshooting: AWS ALB Returns 502 Because the Target Closed the ](aws-alb-502-target-closed-connection-keepalive-timeout-mismatch)
  • [AWS cloud troubleshooting: Fix AWS ALB CreateListener TargetGroupNotFound Err](aws-alb-createlistener-targetgroupnotfound)
  • [AWS cloud troubleshooting: Fix Aws Alb Lambda 502 Bad Gateway Issue in AWS](aws-alb-lambda-502-bad-gateway)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix AWS RDS Connection Limit Exceeded Error", "description": "Troubleshoot RDS connection limit errors. Find connection leaks, tune max_connections, implement pooling, and monitor connection metrics.", "url": "https://www.fixwikihub.com/fix-aws-rds-connection-limit-exceeded", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-03-31T19:23:06.347Z", "dateModified": "2026-03-31T19:23:06.347Z" } </script>