AWS VPC Connectivity Troubleshooting Guide: Routes, SGs, NACLs
VPC connectivity failures follow a predictable pattern. Traffic either reaches its destination or it does not, and the reason is always one of a small number of configuration layers: routing, security groups, NACLs, DNS, or the destination service itself. This guide is a focused incident-response playbook for debugging those layers step by step.
This page covers the specific act of diagnosing and fixing a VPC connectivity failure, not VPC architecture in general. If you want a broader overview of AWS networking problems including load balancers, VPN connections, and Transit Gateway, the AWS network troubleshooting guide is the companion resource to read alongside this one.
Simple explanation
When a resource inside a VPC tries to reach something (another EC2 instance, an RDS database, or an AWS service endpoint), the traffic passes through several independent checkpoints in sequence. Each checkpoint can silently drop the traffic regardless of what the others allow.
The path looks like this:
Source → Route table lookup → NACL outbound (source subnet)
→ Network transit → NACL inbound (destination subnet)
→ Security group (destination resource) → Destination serviceEvery layer must say “yes” before the connection succeeds. A single misconfigured rule anywhere in the chain breaks the whole path.
Imagine your packet is a passenger trying to board a flight. The route table is the departure board: if your destination is not listed, you never find a gate. The NACL on the source subnet is the security scanner on the way out of the terminal. The NACL on the destination subnet is the scanner at arrivals. The security group is the gate agent who checks your boarding pass one final time. The application is the plane door itself. Every checkpoint is independent. Being waved through one of them does not help if another one turns you away.
Understanding the error message you see matters:
- Connection timed out: the packet was sent but no response came back. This usually means the routing is wrong (the packet went nowhere), a NACL silently dropped it, or a security group’s implicit deny discarded it. Timeouts mean packets disappeared somewhere.
- Connection refused: the packet reached the destination IP and port, but nothing was listening or the service actively rejected it. The network path works. The problem is at the application layer: the service is not running, it is bound to the wrong interface, or a firewall on the OS itself is blocking it.
- DNS failure / hostname not resolving: the client could not translate the hostname to an IP address. No packet was ever sent. This is a DNS configuration problem, not a routing or firewall problem. Fix DNS resolution first before checking anything else.
Knowing which error you see narrows the search immediately.
When to use this guide
Use this guide when you are actively debugging one of these situations:
- EC2 cannot reach the internet: outbound requests time out or fail from a running instance
- EC2 cannot reach another EC2 instance: private IP connections between instances are failing
- Lambda in a VPC cannot reach AWS services: calls to S3, Secrets Manager, SSM, or CloudWatch are timing out
- Application cannot connect to RDS: database connections time out or are refused
- Private subnet cannot reach S3, Secrets Manager, or SSM: no NAT gateway, no VPC endpoint, or the endpoint exists but is misconfigured
- DNS works inconsistently or fails inside the VPC: some hostnames resolve, others do not, or resolution is intermittent
- Cross-VPC or PrivateLink connectivity is failing: traffic between peered VPCs or via a VPC endpoint service is not reaching the destination
How it works
Use this as your first-pass checklist. Work top to bottom. The most common causes come first.
| Symptom | Most likely cause | First thing to check |
|---|---|---|
| All outbound traffic times out | No 0.0.0.0/0 route in route table | Route table associated with the subnet |
| Internet access fails from public subnet | Instance has no public IP | PublicIpAddress field on the instance |
| Internet access fails from private subnet | No NAT gateway or NAT route missing | Route table for 0.0.0.0/0 pointing to nat- |
| Instance-to-instance traffic fails in same VPC | Security group on destination blocking inbound | Inbound rules on the destination SG |
| Traffic works outbound but not inbound | NACL missing return traffic rule | NACL entries on both subnets, outbound and inbound |
| S3 / DynamoDB calls fail from private subnet | Missing gateway endpoint or route | VPC endpoint for S3 and the route table |
| Secrets Manager / SSM calls fail | Missing interface endpoint | Interface endpoint for the service, its SG, and its DNS |
| DNS lookup fails inside VPC | VPC DNS settings or private hosted zone | enableDnsSupport and enableDnsHostnames on the VPC |
| Path exists but app still fails | Application layer: service not listening | Port binding, OS firewall, or TLS certificate |
Check routes and subnet type
Route tables are the first checkpoint. If no route exists for the destination, the packet never leaves the subnet.
Every subnet has exactly one route table associated with it. All subnets have a local VPC route (e.g., 10.0.0.0/16 local) that handles all intra-VPC traffic automatically. Internet-bound traffic needs an additional route.
# Get the route table associated with a subnet
aws ec2 describe-route-tables \
--filters "Name=association.subnet-id,Values=subnet-0abc123" \
--query 'RouteTables[0].Routes'What to look for in the output:
0.0.0.0/0pointing toigw-*: public subnet with a direct internet gateway route0.0.0.0/0pointing tonat-*or a NAT gateway ID: private subnet with internet access via NAT- No
0.0.0.0/0entry at all: the subnet has no internet route
If the route is missing, either the wrong route table is associated with the subnet, or the route itself was never added. Fix: associate the correct route table, or add the missing route.
Check which route table is actually associated
A common mistake is assuming a subnet uses the main route table when it was explicitly associated with a different one:
# List all route table associations for a VPC
aws ec2 describe-route-tables \
--filters "Name=vpc-id,Values=vpc-0abc123" \
--query 'RouteTables[*].{ID:RouteTableId,Associations:Associations[*].SubnetId}'Check public IP vs private subnet vs NAT
Understanding the difference between public and private IP addresses is essential here. For internet-bound traffic, the type of IP and subnet determines the correct path.
Public subnet (route to internet gateway): The instance must have a public IP or Elastic IP. The internet gateway performs NAT between the public IP and the private IP. Without a public IP, return traffic from the internet has nowhere to go.
# Check whether the instance has a public IP
aws ec2 describe-instances \
--instance-ids i-1234567890abcdef0 \
--query 'Reservations[0].Instances[0].PublicIpAddress'If the result is null, either assign an Elastic IP or enable auto-assign public IP on the subnet and launch a new instance (existing instances cannot be retroactively assigned auto-assigned IPs).
Private subnet (route to NAT gateway): The instance uses a private IP only. All outbound internet traffic is routed through the NAT gateway, which performs the source IP translation. The instance does not need a public IP. Verify:
- The NAT gateway exists and is in
availablestate - The private subnet’s route table has
0.0.0.0/0pointing to the NAT gateway ID - The NAT gateway itself is in a public subnet with a route to an internet gateway
# Check NAT gateway status
aws ec2 describe-nat-gateways \
--filter "Name=vpc-id,Values=vpc-0abc123" \
--query 'NatGateways[*].{ID:NatGatewayId,State:State,SubnetId:SubnetId}'Check security groups
Security groups are stateful firewalls attached to individual network interfaces. Stateful means that if outbound traffic is allowed, the inbound response is automatically permitted; you only need to configure one direction for a connection you initiate.
A security group is like a hotel room keycard. When you swipe it to enter, the door system remembers the context and lets you exit from the inside without swiping again. Compare that to a NACL (covered next), which works more like a turnstile at a subway station. It checks your ticket every single time you pass through in either direction, with no memory of your previous pass. Forget to configure the return trip and you are stuck at the gate even though you got in just fine.
The critical rule: security groups default to deny all inbound. Every EC2 instance, RDS instance, Lambda ENI, and load balancer starts with no inbound access until you explicitly add rules. This is the most common cause of connectivity failures.
# Check inbound rules on the destination's security group
aws ec2 describe-security-groups \
--group-ids sg-destination \
--query 'SecurityGroups[0].IpPermissions'Things to verify:
- The correct port is open (e.g., 5432 for PostgreSQL, 3306 for MySQL, 443 for HTTPS)
- The source is correctly specified as a CIDR range, another security group ID, or
0.0.0.0/0 - The security group is actually attached to the right resource, not a different instance or interface
- Outbound rules have not been restricted (the default is allow all; check
IpPermissionsEgress)
Using security group references: Instead of using IP addresses (which change), reference the source instance’s security group ID in the destination’s inbound rule. This adapts automatically when instances are replaced.
# Verify which security groups are attached to an instance
aws ec2 describe-instances \
--instance-ids i-1234567890abcdef0 \
--query 'Reservations[0].Instances[0].SecurityGroups'Check NACLs and ephemeral ports
Network ACLs are stateless firewalls that apply at the subnet level. Stateless means return traffic is not automatically allowed; you must explicitly permit both directions. This is the single most common NACL mistake.
By default, the AWS default NACL allows all traffic in both directions. Problems only arise if someone has modified it or created a custom NACL.
# Get the NACL associated with a subnet
aws ec2 describe-network-acls \
--filters "Name=association.subnet-id,Values=subnet-0abc123" \
--query 'NetworkAcls[0].Entries'The output lists rules with Egress: true (outbound) or Egress: false (inbound). Rules are evaluated in number order, lowest first. The first matching rule wins.
Ephemeral ports trap: When a client opens a TCP connection, the OS assigns a temporary source port in the ephemeral range (typically 1024-65535, often 32768-60999 on Linux). The server’s response flows back to that ephemeral port on the client. If the source subnet’s NACL outbound rules do not include a rule allowing TCP traffic to the ephemeral port range, the return traffic is silently dropped even though the request was allowed outbound. The symptom is: the request leaves fine, but nothing ever comes back. Fix by adding an outbound NACL rule on the source subnet allowing TCP port range 1024-65535 to the destination CIDR.
Check DNS and Route 53 private hosted zones
DNS failures look identical to connectivity failures at the application level. Before checking routes or security groups, confirm the hostname actually resolves to the expected IP.
# From inside the VPC (via SSM Session Manager or EC2 connect)
nslookup mydb.internal.example.com
dig mydb.cluster-xyz.us-east-1.rds.amazonaws.comVPC DNS settings: Two VPC attributes must be enabled for DNS to work correctly inside the VPC:
aws ec2 describe-vpc-attribute \
--vpc-id vpc-0abc123 \
--attribute enableDnsSupport
aws ec2 describe-vpc-attribute \
--vpc-id vpc-0abc123 \
--attribute enableDnsHostnamesenableDnsSupport must be true for DNS resolution to work at all. enableDnsHostnames must be true for instances to receive public DNS hostnames.
Private hosted zones: A Route 53 private hosted zone must be explicitly associated with each VPC that needs to use it. A common mistake is creating the private zone and forgetting to associate it with the VPC containing the resources that need to resolve those names.
# List VPC associations for a private hosted zone
aws route53 get-hosted-zone --id /hostedzone/ZONE_ID \
--query 'VPCs'For deeper DNS debugging, see the DNS resolution problems guide.
Check the destination service or application layer
If routing is correct, security groups allow the traffic, NACLs are not blocking it, and DNS resolves, but the connection is still refused, the problem is at the application layer, not the network.
Things to check at the destination:
- Is the service actually running? Check the process (
systemctl status,ps aux, CloudWatch metrics for the service) - Is it listening on the correct port and interface? A service listening only on
127.0.0.1(localhost) is not reachable from outside the instance. It must bind to0.0.0.0or the private IP - Is the OS-level firewall (
iptables,firewalld) active? This is a separate layer from security groups and can block traffic that security groups would allow - For RDS: check that the database is in
availablestate and that the parameter group or SSL settings are not preventing the connection
A “connection refused” error (TCP RST) confirms the packet reached the destination. A timeout means it did not.
Check VPC endpoints and private AWS service access
By default, traffic from inside a VPC to AWS-managed services (S3, DynamoDB, Secrets Manager, SSM, CloudWatch, etc.) does not stay inside the AWS private network. It exits through a public service endpoint. From a private subnet with no NAT gateway, that traffic has nowhere to go and will time out silently.
There are two types of VPC endpoints:
Gateway endpoints: for S3 and DynamoDB only. Free. Added as an entry in the route table rather than creating a network interface.
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0abc123 \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-0abc123 \
--vpc-endpoint-type GatewayInterface endpoints (PrivateLink): for most other AWS services including Secrets Manager, SSM, CloudWatch, ECR, STS, and many more. Creates an ENI with a private IP inside your subnet. The service hostname resolves to that private IP via private DNS.
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0abc123 \
--service-name com.amazonaws.us-east-1.secretsmanager \
--vpc-endpoint-type Interface \
--subnet-ids subnet-0abc123 subnet-0def456 \
--security-group-ids sg-0endpoint123 \
--private-dns-enabledEndpoint troubleshooting checklist:
- Does the endpoint exist?
aws ec2 describe-vpc-endpoints --filters "Name=vpc-id,Values=vpc-0abc123" - Is the gateway endpoint’s route in the correct route table (the one associated with the subnet that needs access)?
- Does the interface endpoint’s security group allow inbound HTTPS (port 443) from the calling resource?
- Is private DNS enabled on the interface endpoint? Without it, the AWS service hostname still resolves to the public IP
- Does the endpoint policy allow the action and resource? A restrictive VPC endpoint policy can block traffic even when the network path is open
Use VPC Flow Logs
VPC Flow Logs record metadata about IP traffic flowing through network interfaces in your VPC. They show source IP, destination IP, destination port, protocol, packet count, byte count, and whether the traffic was ACCEPTED or REJECTED. They do not capture packet contents.
Enable Flow Logs before you need them: Flow Logs capture traffic as it flows. They cannot recover anything that was not logged at the time. If Flow Logs are not enabled when the incident happens, you have no wire-level evidence. Enable them proactively on all production VPCs.
Enable Flow Logs on a VPC and deliver to CloudWatch Logs:
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-0abc123 \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /vpc/flow-logs \
--deliver-logs-permission-arn arn:aws:iam::111122223333:role/flow-logs-roleReading a flow log record:
version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status
2 111122223333 eni-0abc123 10.0.1.45 10.0.2.100 52341 5432 6 1 40 1710854400 1710854460 REJECT OKThis record shows source 10.0.1.45 attempted TCP (protocol 6) to 10.0.2.100:5432 and was REJECTED. The traffic reached interface eni-0abc123 but was blocked. Routing is working; a security group or NACL is blocking it.
Query rejected traffic in CloudWatch Logs Insights:
fields @timestamp, srcAddr, dstAddr, dstPort, action
| filter action = "REJECT"
| filter dstAddr = "10.0.2.100"
| sort @timestamp desc
| limit 50Reading the results: A REJECT in flow logs means a security group or NACL blocked the traffic. If you see traffic reaching the destination ENI but being rejected, routing is correct. Focus on security groups and NACLs. If you see no flow log record at all for traffic you expected, the packet is being dropped before it reaches an ENI, which points to a routing or subnet configuration issue.
Use Reachability Analyzer
Reachability Analyzer tests whether a network path between two AWS resources is theoretically possible, without sending real traffic. It models your current routing rules, security group rules, and NACLs and tells you exactly which resource (if any) is blocking the path.
# Create a path between two resources
aws ec2 create-network-insights-path \
--source i-1234567890abcdef0 \
--destination i-0fedcba9876543210 \
--protocol tcp \
--destination-port 5432
# Start the analysis (returns a network-insights-analysis-id)
aws ec2 start-network-insights-analysis \
--network-insights-path-id nip-0abc123
# Get results (allow ~30 seconds)
aws ec2 describe-network-insights-analyses \
--network-insights-analysis-ids nia-0abc123 \
--query 'NetworkInsightsAnalyses[0].[NetworkPathFound,Explanations]'If NetworkPathFound is false, the Explanations array identifies exactly which security group rule, NACL entry, or route table gap is blocking the path. This eliminates manual guesswork when debugging complex paths.
Reachability Analyzer supports paths between EC2 instances, network interfaces, internet gateways, VPC peering connections, VPN gateways, and transit gateways.
Scenario-based troubleshooting
EC2 cannot reach the internet
Work through in this order:
- Check the subnet’s route table for a
0.0.0.0/0route. If missing, this is the problem. - If the route goes to an internet gateway (
igw-): check that the instance has a public IP or Elastic IP. Without one, return traffic cannot reach it. - If the route goes to a NAT gateway (
nat-): verify the NAT gateway is inavailablestate and is in a public subnet that itself has a route to an internet gateway. - Check the security group’s outbound rules. The default is allow-all outbound, but this can be restricted.
- Check the subnet’s NACL for outbound rules that might block the traffic or inbound rules blocking the response on ephemeral ports 1024-65535.
EC2 cannot reach another EC2 instance
Intra-VPC traffic routes via the local VPC route automatically. No internet gateway or NAT gateway is needed. The local route is always present and cannot be removed.
The problem is almost always a security group:
- Get the destination instance’s private IP:
aws ec2 describe-instances --instance-ids i-dest --query 'Reservations[0].Instances[0].PrivateIpAddress' - Check the destination instance’s security group inbound rules for the relevant port and protocol. The source should reference either the source instance’s security group ID or its private IP CIDR.
- If the instances are in different subnets, check both subnets’ NACLs: outbound on the source subnet and inbound on the destination subnet, plus return traffic rules.
- Confirm the security group with the inbound rule is actually attached to the destination instance, not a different one.
Lambda in a VPC cannot reach AWS services
Lambda functions placed in a VPC use the VPC’s network path, not the default Lambda internet path. A Lambda in a private subnet with no NAT gateway and no VPC endpoints is effectively network-isolated.
The silent Lambda timeout: When Lambda in a VPC fails to reach S3 or Secrets Manager, it does not get a clear error. The function simply times out after 15 minutes (or your configured timeout). The fix depends on which service you are calling: S3 and DynamoDB need gateway endpoints; Secrets Manager, SSM, CloudWatch, ECR, and STS need interface endpoints with private DNS enabled.
- S3 and DynamoDB: require a gateway endpoint added to the route table of the Lambda’s subnets
- Secrets Manager, SSM Parameter Store, CloudWatch, ECR, STS, and most other services: require interface endpoints (PrivateLink) in the Lambda’s VPC, with private DNS enabled
- General internet access: requires a NAT gateway in a public subnet and a
0.0.0.0/0route in the Lambda’s private subnet pointing to the NAT gateway
Check which subnets the Lambda function is associated with, then verify the route tables and endpoints for those subnets.
aws lambda get-function-configuration \
--function-name my-function \
--query 'VpcConfig'App cannot connect to RDS
RDS connection failures are a specific subset of EC2-to-resource connectivity. See the dedicated RDS connection refused guide for a complete walkthrough. The key checks:
- The RDS instance’s security group must have an inbound rule for the database port (5432 for PostgreSQL, 3306 for MySQL) from the application server’s security group or subnet CIDR
- The RDS instance must be in
availablestate - The application is connecting to the correct endpoint. Multi-AZ failovers change the underlying IP but not the endpoint DNS name, so typos here are a common problem.
- If using SSL, the certificate must be valid and the application must trust the RDS CA bundle
- Check that there is no NACL on the RDS subnet blocking the database port or the ephemeral return-traffic ports
DNS works inconsistently inside the VPC
Intermittent or partial DNS failures inside a VPC are often caused by:
- A private hosted zone not associated with all VPCs that need to resolve those names
- A split-horizon DNS conflict where the same hostname resolves differently inside vs. outside the VPC
- A custom DNS server (on-premises resolver forwarded via Route 53 Resolver inbound endpoint) failing to forward
.amazonaws.comor.internalqueries to the VPC resolver at169.254.169.253 enableDnsSupportdisabled on the VPC (all DNS lookups fail)
To test from inside the instance using SSM Session Manager:
# Test the AWS-provided VPC resolver directly
dig @169.254.169.253 myservice.internal.example.com
# Check if the correct IP is returned vs. the public IP
nslookup secretsmanager.us-east-1.amazonaws.comIf the VPC resolver returns a public IP for a service that has an interface endpoint with private DNS enabled, the endpoint’s private DNS is not working. Check that private DNS is enabled on the endpoint and that enableDnsSupport is true on the VPC.
For full DNS debugging steps, see DNS resolution problems.
VPC endpoint or PrivateLink path is failing
If an interface endpoint exists but traffic is still not reaching the service:
- DNS resolution: confirm the service hostname resolves to a private IP (in the
10.x.x.xor172.x.x.xrange), not the public endpoint IP. If it resolves to a public IP, private DNS is not enabled on the endpoint orenableDnsSupportis false on the VPC. - Endpoint security group: the interface endpoint itself has a security group. It must allow inbound HTTPS (port 443) from the resources that will use it.
- Route table (gateway endpoints only): verify the route for the S3 or DynamoDB prefix list appears in the route table of the subnet that needs access.
- Endpoint policy: a custom VPC endpoint policy may be restricting which actions or resources are accessible. The default policy allows all access; a restrictive custom policy can silently block specific API calls.
- Cross-account PrivateLink: if consuming a PrivateLink endpoint service from another account, verify that the service has accepted the connection request and that the endpoint is in
availablestate (notpending-acceptance).
Common mistakes
- Public subnet, no public IP: the subnet has a route to an internet gateway, but the instance never got a public IP. The outbound request leaves the instance, hits the internet gateway, and the internet gateway has no public IP to source the traffic from. The instance receives no response. Fix: assign an Elastic IP or enable auto-assign public IP on the subnet and use a new instance.
- Wrong route table associated with the subnet: the private subnet is accidentally associated with the main route table, which has a direct internet gateway route, making it behave as public. Or the public subnet is associated with a route table that has no internet gateway route. Always explicitly associate route tables rather than relying on the main route table default.
- Security group attached to the wrong resource: the inbound rule was added to a security group that is not the one attached to the destination instance or RDS instance. Verify the security group association with
aws ec2 describe-instances --instance-ids i-xxx --query 'Reservations[0].Instances[0].SecurityGroups' - NACL missing ephemeral port return traffic rules: a NACL allows TCP port 443 outbound but has no rule allowing inbound traffic on ports 1024-65535. The response from the server arrives on an ephemeral port and is dropped by the NACL. The application sees a timeout even though the outbound request was sent successfully.
- Lambda in a private subnet without endpoints or NAT: Lambda is placed in a VPC for security reasons (private database access), but the subnet has no NAT gateway and no interface endpoints for AWS services. The function silently times out when calling S3, Secrets Manager, or SSM. Each service needs either a NAT gateway route or a dedicated interface endpoint.
- VPC endpoint exists but the route table or security group is wrong: a gateway endpoint for S3 was created, but the route table selected during creation is not the one associated with the subnet making the requests. Or an interface endpoint was created but its security group does not allow inbound 443 from the calling resources. The endpoint exists; the path still does not work.
- Modifying the default NACL: the default NACL applies to every subnet in the VPC that is not explicitly associated with a custom NACL. Modifying it unintentionally affects all those subnets. Create dedicated custom NACLs and associate them explicitly with the subnets you intend to control.
- Private hosted zone not associated with the correct VPC: a Route 53 private hosted zone is created for internal service discovery but is only associated with one VPC. Resources in a second VPC (including Lambda functions or peered VPCs) cannot resolve the hostnames. Add the VPC association to the hosted zone.
VPC Flow Logs vs Reachability Analyzer
These tools solve different problems. Using the right one first saves time.
| VPC Flow Logs | Reachability Analyzer | |
|---|---|---|
| What it does | Records actual traffic metadata (ACCEPT/REJECT) at the network interface level | Models the theoretical network path between two resources against current config |
| Requires live traffic | Yes: must capture the failing request as it happens | No: works against configuration, no packets needed |
| Must be pre-enabled | Yes: cannot recover historical traffic | No: runs on demand at any time |
| Cost | Ongoing ingestion and storage cost | Per-analysis charge (~$0.10 per analysis) |
| What it identifies | Whether traffic was accepted or rejected, and on which interface | Exactly which rule (SG, NACL, route) prevents the path |
| What it cannot tell you | Which specific rule caused a rejection, or whether a path would work before traffic flows | Whether traffic is actually flowing or what the application-layer result is |
| Best used when | Traffic is flowing and you need evidence of what is being blocked or accepted | You want to confirm a path is theoretically possible, or you cannot reproduce the failure on demand |
Recommended workflow during an incident: Enable Flow Logs immediately if not already on and reproduce the failure to capture REJECT records. Then use Reachability Analyzer to identify the blocking rule without reproducing the failure again. Fix the rule and re-run Reachability Analyzer to confirm the path is now open. Verify with a real request.
Summary
- Work through connectivity layers in order: route table, public IP or NAT, security group, NACL, DNS, application layer.
- Connection timed out means a packet disappeared (routing or firewall). Connection refused means the packet arrived but the service rejected it. DNS failure means no packet was sent yet.
- NACLs are stateless. Missing ephemeral port return rules cause silent one-way timeouts.
- Private subnets with no NAT gateway need VPC endpoints to reach S3, Secrets Manager, SSM, and other AWS services. Gateway endpoints cover S3 and DynamoDB; interface endpoints cover everything else.
- Flow Logs show what actually happened to traffic at the wire level. Reachability Analyzer shows whether a path is theoretically possible. Use both.
Frequently asked questions
What is the fastest way to tell whether the problem is routing, security groups, or NACLs?
Start with the route table. If no route exists for the destination, the packet never leaves the subnet and security groups or NACLs are irrelevant. If a route exists, check the security group on the destination next, since groups are stateful and easier to verify. If traffic works in one direction but not the other, a NACL is almost always the cause. It is stateless and requires explicit rules for both directions, including ephemeral return-traffic ports. AWS Reachability Analyzer can confirm exactly which layer is blocking a specific path without sending real packets.
Do I need VPC Flow Logs enabled before the incident?
Yes. Flow Logs capture traffic as it happens and cannot recover anything that was not logged. Enable Flow Logs proactively on production VPCs and deliver them to CloudWatch Logs or S3. If you are responding to an ongoing issue right now, enable them immediately and reproduce the failing request to capture evidence.
When should I use Reachability Analyzer instead of Flow Logs?
Use Reachability Analyzer when you want to confirm whether a network path is theoretically possible, before traffic flows, or when you cannot reproduce the failure on demand. It models your routing rules, security group rules, and NACLs against a hypothetical packet without real traffic. Use Flow Logs when traffic is already flowing and you want to see what is actually being accepted or rejected at the wire level. The two tools complement each other.
Why can Lambda in a private subnet reach some things but not S3 or Secrets Manager?
Lambda in a private subnet with no NAT gateway can only reach resources inside the VPC via private IP. S3 and Secrets Manager are AWS-managed services whose default endpoints are public. Traffic to them needs either a NAT gateway (to route via the internet) or a VPC endpoint (to stay fully private). S3 and DynamoDB use gateway endpoints added to the route table. Secrets Manager, SSM, CloudWatch, and most other AWS services use interface endpoints (PrivateLink). Without one of these options, Lambda will time out silently.
Can DNS make a network problem look like a connectivity problem?
Yes. If a hostname fails to resolve, the connection fails before any packet reaches the network layer and the error looks identical to a blocked connection from the application side. Common VPC causes include DNS resolution being disabled on the VPC, a private hosted zone not associated with the correct VPC, or an on-premises DNS resolver not forwarding .amazonaws.com queries to the VPC DNS resolver at 169.254.169.253. Always verify the hostname resolves to the expected IP before assuming the network path is broken.