Skip to content

RDS connection timeouts: security groups, subnets, and public accessibility debugged in order

A connection timeout to RDS is a network-path problem, not a database problem. Here is the order to debug it: security groups, then subnets and routing, then the publicly accessible flag and DNS.

A connection to RDS that hangs and then times out means your packets are being silently dropped somewhere on the network path — which on AWS points at security groups first, subnets and routing second, and the publicly accessible flag third. This is different from “connection refused” (you reached the host, wrong port or engine down) and from an authentication error (the network is fine, credentials are not). Timeouts are debugged in a fixed order, and the security group is the answer roughly four times out of five.

What’s happening

RDS instances live inside a VPC and are reachable only along paths you have explicitly allowed. Four gates sit between a client and the database port, and any one of them failing produces the identical symptom — a hang, then a timeout:

The security group attached to the DB instance must allow inbound traffic on the database port (3306 for MySQL/MariaDB, 5432 for Postgres, 1433 for SQL Server) from the client’s source. Security groups drop unmatched traffic silently — no rejection packet, hence the hang. The most reliable pattern references the application’s security group as the source rather than IP ranges.

Subnets and routing. The DB subnet group determines which subnets the instance can occupy. A client in a peered VPC, another region, or on-premises over VPN needs routes both ways; network ACLs on the subnets, if anyone has customized them, need the port plus ephemeral return ports open.

The publicly accessible flag. If PubliclyAccessible is false, the instance’s endpoint DNS resolves only to a private IP, and nothing outside the VPC can reach it, ever. If it is true and the instance sits in public subnets with an internet gateway route, the endpoint resolves to a public IP from outside the VPC and a private IP from inside — a detail that explains many “works from the office, times out from EC2” mysteries in reverse.

DNS. Always connect to the endpoint hostname, never a resolved IP — the underlying IP changes on failover and maintenance.

What to check first

  • Where are you connecting from? A laptop on home Wi-Fi, an EC2 instance in the same VPC, a Lambda, and a container in Fargate each have a different network path. Establish this before touching anything.
  • Timeout or refused? Connection refused means the network path works — skip to checking the port and engine status. A hang means keep reading.
  • The DB security group’s inbound rules — in RDS > Databases > your-instance > Connectivity & security, click through to the security group.
  • What the endpoint resolves to from where you are: private IP (10.x, 172.16-31.x, 192.168.x) from outside the VPC means the publicly accessible flag is your problem.
  • Did this ever work? A path that worked yesterday points to a changed rule or rotated resource, not a design gap.

How to verify

Test raw TCP reachability first — it separates network from credentials instantly:

# From the client that is failing (nc, or bash's /dev/tcp)
nc -zv -w 5 prod-db.abc123xyz.ca-central-1.rds.amazonaws.com 5432

# What does the endpoint resolve to from here?
dig +short prod-db.abc123xyz.ca-central-1.rds.amazonaws.com

Then inspect the gates from the AWS side:

# The instance's security groups, subnet group, and public flag in one call
aws rds describe-db-instances --db-instance-identifier prod-db \
  --query 'DBInstances[0].[PubliclyAccessible,DBSubnetGroup.DBSubnetGroupName,
           VpcSecurityGroups[].VpcSecurityGroupId,Endpoint.Address,Endpoint.Port]'

# The inbound rules on that security group
aws ec2 describe-security-groups --group-ids sg-0abc123 \
  --query 'SecurityGroups[0].IpPermissions'

For a definitive answer on a VPC-internal path, VPC Reachability Analyzer (VPC > Reachability Analyzer) traces source to destination and names the exact blocking component — worth the few minutes it takes on any non-obvious case.

The runbook

  1. Fix the security group first. Add an inbound rule on the DB security group for the engine port with the application’s security group as the source (same VPC), or the peered CIDR / VPN CIDR for cross-network paths. This resolves the large majority of RDS timeouts. Avoid 0.0.0.0/0 on a database port — if you are tempted, you actually want SSM or a bastion.
  2. Check the client’s outbound rules and NACLs. Security groups are stateful, so default outbound-allow covers the return path — but a locked-down egress SG or a customized network ACL (stateless — needs ephemeral ports 1024-65535 on the return) breaks it. Default NACLs allow everything; only debug them if someone changed them.
  3. Verify routing for cross-VPC and hybrid paths. Peering needs route entries in both VPCs’ route tables plus SG rules referencing the peer CIDR. VPN and Direct Connect need the on-prem CIDR routed and allowed. Same-VPC traffic needs no route work — if same-VPC times out, it is the SG or NACL, full stop.
  4. Sort out public accessibility deliberately. If a developer laptop must reach the database directly, either make the instance publicly accessible (it must be in subnets with an IGW route, and modifying the flag is a config change, not a rebuild) — or, better, keep it private and connect through an SSM port-forwarding session or a bastion. Public database endpoints are a standing invitation to credential-stuffing traffic.
  5. Reconnect via the endpoint hostname. If the client had an IP hard-coded or cached (JVMs with default DNS caching are notorious), it breaks after any failover. Connect by name and honour DNS TTLs.
  6. Only then suspect the instance. If TCP connects but the driver still times out, look at the engine: an instance in rebooting or storage-full state, or one saturated with connections — which is a different article: too many connections.

When this is the wrong move

If the error is an authentication failure, TLS mismatch, or connection refused, network debugging is wasted effort — the path is proven. If connections succeed but drop after exactly N seconds of idleness, you are fighting an idle timeout (NAT gateway 350s, firewall state tables) and the fix is TCP keepalives, not rules. And resist “solving” a timeout by flipping PubliclyAccessible to true — it often will not work anyway (private-only subnets), and when it does, you have widened exposure to fix a rule you could have scoped precisely. The Amazon VPC documentation covers security group semantics; our own security groups vs NACLs covers which layer to debug when.

Common mistakes

  • Adding the client’s public IP to the security group when the client is an EC2 instance connecting inside the VPC from its private IP — the rule never matches.
  • Debugging NACLs, route tables, and DNS for an hour before reading the security group’s inbound rules once.
  • Hard-coding the resolved IP of the endpoint “for reliability” — it is the opposite; the IP changes on failover.
  • Assuming Lambda has internet-style access to RDS: a VPC-attached Lambda needs its SG allowed inbound on the DB SG; a non-VPC Lambda cannot reach a private instance at all.

Prevention

  • Reference security groups, not IPs, for app-to-database rules — they survive autoscaling and redeployment.
  • Keep production databases private and standardize developer access through SSM port forwarding.
  • Name security groups by role (prod-db-postgres, prod-app-web) so rule intent is auditable at a glance.
  • Record the intended network path per environment in the runbook — most timeout incidents are someone rediscovering it under pressure.
  • Alarm on application-side connection error rates so a broken path surfaces before users report it.

Connection timeouts feel opaque, but the gate order never changes: security group, NACL and routes, public accessibility, DNS — checked in that order, most are diagnosed in under ten minutes. If nobody on your team truly owns the AWS environment end to end, that is the root of most of these problems — Stack Harbor runs AWS accounts daily under AWS Operations, and you can book an AWS review.