AWS VPC Networking: Full Request Journey

You can outsource your thinking but not your understanding.

A packet-level trace of a typical web service deployed on AWS — from DNS resolution through load balancer, private subnet, database, and back out to an external API. No theory, just the path.

Diagrams show the request direction. Responses retrace the same path — Security Groups handle this automatically (stateful), NACLs require explicit return rules (stateless).


Service Diagram

                                          ┌─────────────────────┐
                                    ┌───► │  RDS  (Postgres)    │
                                    │     └─────────────────────┘
┌──────────┐     ┌──────────┐     ┌───┴──────────┐
│  Client  │────►│    LB    │────►│  App Server  │
└──────────┘     └──────────┘     └───┬──────────┘
                                      │
                                      ▼
                                ┌─────────────────────┐
                                │  External Service   │
                                │  (api.stripe.com)   │
                                └─────────────────────┘

Deployment Design

Who can reach what, and why each resource is placed where it is.

ResourceSubnetInternet-FacingAccessible FromWhy
ALB Public Yes Anyone (0.0.0.0/0 on :443) It's the front door. Must accept requests from any client on the internet.
NAT Gateway Public Yes (EIP only) Private subnet (outbound only) Needs a public IP to forward outbound traffic. The EIP is the source address Stripe sees — nothing on the internet can initiate a connection to it.
EC2 Private No ALB only (SG reference to ALB-SG) Application logic shouldn't be directly internet-accessible. Locking the SG to ALB-SG means even someone who knows the private IP can't reach it from outside.
RDS Private No EC2 only (SG reference to EC2-SG) The database never needs to speak to the internet — not inbound, not outbound. Only the app layer should have a connection to it.

The pattern is a strict tier model: public subnet holds only what must be internet-reachable, private subnet holds everything else. Security Groups then restrict access within those tiers to named sources rather than IP ranges, so adding a second EC2 to the Target Group automatically inherits the right to reach RDS without any rule changes.

Reference Values

ResourceValue
Client203.0.113.5
Domainapi.hookly.com54.23.145.67
VPC CIDR10.0.0.0/16
Public Subnet10.0.1.0/24
Private Subnet10.0.2.0/24
ALB54.23.145.67:443
NAT Gateway10.0.1.100 / EIP 52.14.88.12
EC2 Web Server10.0.2.15:8080
RDS Postgres10.0.2.50:5432
External Serviceapi.stripe.com

Acronyms

AcronymFull FormWhat it means
VPCVirtual Private CloudYour isolated private network inside AWS
IGWInternet GatewayConnects the VPC to the public internet
NATNetwork Address TranslationRewrites IP addresses as packets cross a boundary
SNATSource NATSpecifically replaces the source IP — what NAT GW does to hide your EC2's private IP
NACLNetwork Access Control ListStateless firewall rules applied at the subnet boundary
SGSecurity GroupStateful firewall rules applied to a specific resource
ALBApplication Load BalancerLayer 7 load balancer — routes HTTP/S traffic to targets
TGTarget GroupThe set of EC2s the ALB forwards traffic to
EC2Elastic Compute CloudA virtual machine (your app server)
RDSRelational Database ServiceAWS managed relational database (Postgres, MySQL, etc.)
EIPElastic IPA static public IP address you own in AWS
CIDRClassless Inter-Domain RoutingIP range notation — 10.0.0.0/16 means 65,536 addresses
DNSDomain Name SystemTranslates api.hookly.com to an IP address
TLSTransport Layer SecurityEncryption protocol behind HTTPS

Key Concepts

ConceptStateful?What it does
Security Group Yes Firewall on a resource. Allow inbound :443 and the response is automatically allowed out. No extra outbound rule needed.
NACL No Firewall at the subnet boundary. Allow inbound :443 and you must also explicitly allow outbound :1024–65535 (ephemeral ports) or the response is dropped. Rules evaluated in order by rule number — first match wins.
Route Table Decides where a packet goes next (IGW, NAT GW, or stays local). Longest prefix match — most specific route wins. Routing decision only, not allow/deny.
Internet Gateway The door between your VPC and the public internet.
NAT Gateway Lets private resources reach the internet without being reachable from it. SNAT: hides EC2's private IP behind the EIP.
ALB Terminates TLS, then forwards to a healthy target in the Target Group.

Architecture Overview

               ┌─────────────── INTERNET ────────────────────────────┐
               │  Client 203.0.113.5           api.stripe.com        │
               └──────────┬─────────────────────────────▲────────────┘
                          │                             │
               ┌──────────▼───────────────────────────────────────────┐
               │              Internet Gateway (IGW)                  │
               └──────────┬───────────────────────────▲───────────────┘
                          │                           │
┌─────────────────────────▼───────────────────────────┼──────────────────┐
│ VPC 10.0.0.0/16                                     │                  │
│                                                     │                  │
│  ┌──── Public Subnet 10.0.1.0/24 ───────────────────┴──────────────┐   │
│  │                        │                                        │   │
│  │                        ▼                                        │   │
│  │   ┌────────────────────┐         ┌────────────────────────────┐ │   │
│  │   │ ALB                │         │ NAT Gateway                │ │   │
│  │   │ 54.23.145.67:443   │         │ 10.0.1.100                 │ │   │
│  │   │ SG: 0.0.0.0/0:443  │         │ EIP: 52.14.88.12           │ │   │
│  │   └────────┬───────────┘         └────────────────────────────┘ │   │
│  └────────────┼───────────────────────────────────────▲────────────┘   │
│               │ :8080                                 │                │
│               ▼                                       │                │
│  ┌──── Private Subnet 10.0.2.0/24 ───────────────────────────────┐     │
│  │               │                                   │           │     │
│  │   ┌───────────▼──────────────────┐                │           │     │
│  │   │ EC2  10.0.2.15:8080          │   outbound ────┘           │     │
│  │   │ SG in: ALB-SG → :8080        │                            │     │
│  │   └───────────┬──────────────────┘                            │     │
│  │               │ :5432                                         │     │
│  │   ┌───────────▼──────────────────┐                            │     │
│  │   │ RDS  10.0.2.50:5432          │                            │     │
│  │   │ SG in: EC2-SG → :5432        │                            │     │
│  │   └──────────────────────────────┘                            │     │
│  └───────────────────────────────────────────────────────────────┘     │
└────────────────────────────────────────────────────────────────────────┘

Inbound Flow — 203.0.113.5 → api.hookly.com

┌────────────────────────────────────────────────────────────────────────────┐
│  INTERNET                                                                  │
│                                                                            │
│  ① Client  203.0.113.5                                                    │
│       DNS:  api.hookly.com  ──►  54.23.145.67   (ALB public IP)            │
│       TCP SYN  ──►  54.23.145.67:443                                       │
└─────────────────────────────┬──────────────────────────────────────────────┘
                              │ ② HTTPS :443
┌─────────────────────────────▼─────────────────────────────────────────────┐
│  Internet Gateway (IGW)                                                   │
└─────────────────────────────┬─────────────────────────────────────────────┘
                              │ ③ routes to VPC
┌── Public Subnet 10.0.1.0/24 ▼───────────────────────────────────────────────┐
│                                                                             │
│  ④ NACL  (stateless — both directions must be explicitly allowed)          │
│       in:  TCP :443  from 0.0.0.0/0              ✓  rule 100                │
│       out: TCP :1024-65535  to 0.0.0.0/0         ✓  ephemeral ports         │
│                                                                             │
│  ⑤ Route Table                                                             │
│       0.0.0.0/0    ──►  igw-0a1b2c3d   (internet traffic exits via IGW)     │
│       10.0.0.0/16  ──►  local                                               │
│                                                                             │
│  ⑥ ALB  54.23.145.67                                                       │
│       SG in:  TCP :443  src 0.0.0.0/0      ✓                                │
│       SG in:  TCP :80   src 0.0.0.0/0      ✓  (redirect → HTTPS)            │
│       SG out: all                          ✓                               │
│       Listener :443  ──►  Target Group  ──►  10.0.2.15:8080                 │
│                                                                             │
└──────────────────────────────┬──────────────────────────────────────────────┘
                               │ ⑦ ALB forwards to target group :8080
┌── Private Subnet 10.0.2.0/24 ▼────────────────────────────────────────────────┐
│                                                                               │
│  ⑧ NACL  (stateless)                                                         │
│       in:  TCP :8080  from 10.0.1.0/24       ✓  (only from public subnet)     │
│       out: TCP :1024-65535  to 10.0.1.0/24   ✓  (ephemeral return traffic)    │
│                                                                               │
│  ⑨ Route Table                                                               │
│       10.0.0.0/16  ──►  local                                                 │
│       0.0.0.0/0    ──►  nat-0x1y2z3w          (outbound internet via NAT)     │
│                                                                               │
│  ⑩ EC2  10.0.2.15:8080                                                       │
│       SG in:  TCP :8080  src sg-alb       ✓  (SG ref — only ALB can reach)    │
│       SG out: all                         ✓                                   │
│              │                                                                │
│              │ ⑪ :5432  (stays within private subnet, SG enforced)           │
│              ▼                                                                │
│       RDS  10.0.2.50:5432                                                     │
│            SG in:  TCP :5432  src sg-ec2  ✓  (SG ref — only EC2 can reach)    │
│                                                                               │
└───────────────────────────────────────────────────────────────────────────────┘

Outbound Flow — EC2 → api.stripe.com

EC2 is in a private subnet — no public IP, no direct internet access. All outbound internet traffic routes through NAT Gateway in the public subnet.
┌── Private Subnet 10.0.2.0/24 ───────────────────────────────────────────────────┐
│                                                                                 │
│  ⑫ EC2  10.0.2.15  calls  api.stripe.com                                        │
│       Route Table:  0.0.0.0/0  ──►  NAT GW (nat-0x1y2z3w)                       │
│                                                                                 │
└──────────────────────────────────────┬──────────────────────────────────────────┘
                                       │ ⑬
┌── Public Subnet 10.0.1.0/24 ─────────▼──────────────────────────────────────────┐
│                                                                                 │
│  ⑭ NAT Gateway  10.0.1.100                                                     │
│       SNAT:  src 10.0.2.15  ──►  EIP 52.14.88.12                                │
│                                                                                 │
│       Stripe sees the request from 52.14.88.12, not the private EC2 IP.         │
│       Response returns:  api.stripe.com → IGW → NAT GW → EC2 10.0.2.15          │
│                                                                                 │
└──────────────────────────────────────┬──────────────────────────────────────────┘
                                       │ ⑮
┌──────────────────────────────────────▼─────────────────────────────────────────┐
│  Internet Gateway (IGW)                                                        │
└──────────────────────────────────────┬─────────────────────────────────────────┘
                                       │ ⑯
┌──────────────────────────────────────▼──────────────────────────────────────────┐
│  INTERNET  ──►  api.stripe.com                                                  │
└─────────────────────────────────────────────────────────────────────────────────┘

Step-by-Step Flow Reference

StepDirectionFromToPortLayerNote
InboundClientDNS53DNSResolves api.hookly.com54.23.145.67
InboundClient 203.0.113.5ALB 54.23.145.67443InternetTCP SYN to ALB public IP
InboundIGWPublic Subnet443IGWRoutes public IP into VPC
InboundIGWPublic Subnet443NACLStateless check — inbound :443 allowed
InboundIGWPublic SubnetRoute Table0.0.0.0/0 → IGW, 10.0.0.0/16 → local
InboundInternetALB 54.23.145.67443Security GroupSG allows :443 from 0.0.0.0/0
InboundALBEC2 10.0.2.158080ALBListener forwards to Target Group
InboundALB subnetPrivate Subnet8080NACLStateless check — inbound :8080 from 10.0.1.0/24
InboundALB subnetPrivate SubnetRoute Table10.0.0.0/16 → local, 0.0.0.0/0 → NAT GW
InboundALBEC2 10.0.2.158080Security GroupSG allows :8080 from ALB-SG only
InternalEC2 10.0.2.15RDS 10.0.2.505432Security GroupSG allows :5432 from EC2-SG only
OutboundEC2 10.0.2.15NAT GW 10.0.1.100anyRoute Table0.0.0.0/0 → NAT GW in private subnet
OutboundPrivate SubnetPublic SubnetanyNACLOutbound ephemeral ports allowed
OutboundNAT GW 10.0.1.100IGWanyNAT GatewaySNAT: 10.0.2.15 → EIP 52.14.88.12
OutboundNAT GW EIPIGWanyIGWRoutes EIP traffic to internet
OutboundIGWapi.stripe.com443InternetStripe sees src 52.14.88.12