connection timed out" to RDS: security group checklist
Gives a security group checklist for connection timed out errors reaching RDS: port test, SG inbound rules, NACLs, route tables, DNS. Use when the DB is healthy but unreachable from a new client. Not for connection refused or authentication failures.
TL;DR
"Connection timed out" to RDS almost always means the network path is blocked, not that the database is down: the security group does not allow your source IP on the DB port. Work the checklist in order: can you reach the port, does the SG allow your IP, is the NACL blocking, is the route table right. Do not restart the database; it is not the problem.
Error / query
"connection timed out" to RDS: security group checklistUse this skill when
- Your app gets "connection timed out" reaching RDS but the DB status is available
- A new app server or Lambda cannot reach a database that older hosts reach fine
- The error started after a security group or VPC change
- You need a repeatable checklist instead of clicking around the console
Not for this skill when
- The error is "connection refused"; that means you reached the host but nothing listens, different problem
- RDS itself shows as failed or storage-full; fix the database first
- Auth fails with "password authentication failed"; the network is fine, the credential is wrong
Steps
Step 1: Test whether the port is reachable at all
timeout 10 bash -c 'echo > /dev/tcp/[db-endpoint]/5432' && echo "port open" || echo "port blocked or timed out"Expected: "port open" means networking is fine and the problem is elsewhere; "timed out" confirms a network-layer block.
Step 2: Check what the RDS security group allows
aws rds describe-db-instances --db-instance-identifier mydb --query 'DBInstances[0].VpcSecurityGroups[].VpcSecurityGroupId' --output textExpected: the SG IDs; take the first one into step 3.
Step 3: List the inbound rules on that security group
aws ec2 describe-security-groups --group-ids [sg-id-from-step-2] --query 'SecurityGroups[0].IpPermissions' --output tableExpected: inbound rules; your source IP (or its SG) must appear on the DB port (5432 for Postgres, 3306 for MySQL). If it does not, that is the fix.
Step 4: Check the subnet NACL is not blocking the return traffic
aws ec2 describe-network-acls --filters Name=vpc-id,Values=[vpc-id] --query 'NetworkAcls[].Entries' --output table | head -20Expected: allow rules for the DB port in both directions; NACLs are stateless, so the ephemeral return range needs an allow too.
Step 5: Verify DNS resolves the endpoint to the right IP
nslookup [db-endpoint] | tail -3Expected: a private IP in your VPC range; a public IP means the endpoint is resolving wrong or the DB is not in the expected VPC.
Variant phrasings
"Cannot connect to RDS from EC2"
Same checklist; the most common cause is the EC2 instance's security group not being listed as a source in the RDS security group.
"RDS connection timeout from Lambda"
Lambda in a VPC needs the RDS SG to allow the Lambda's SG, and the Lambda needs a NAT route if it also calls the internet; check both.
"Connection timed out vs connection refused to RDS"
Timed out is a firewall or routing block (this skill); refused means you got through but the DB is not listening on that port.
Why it happens
RDS security groups default to deny, and every new client (host, Lambda, CI runner) has a new source IP or SG that nobody added. The database is healthy; the front door is just closed to the new arrival.
Edge cases and pitfalls
- Opening the DB port to the all-interfaces address/0 "to test" and forgetting to close it; use your specific IP and set a reminder.
- The SG rule references another SG, but the client was launched into a different SG after a refactor; the reference silently stops matching.
- RDS in a private subnet with no route from the client's subnet; SGs are fine but packets have no path.
- DNS caching on the client can point at an old IP after a failover; flush or wait out the TTL before blaming the SG.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_4oUmtqlkOE9kmPSjKow-zg
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.