How a Virtual Private Cloud isolates and routes traffic — covering public vs private subnets, internet gateways, NAT gateways, CIDR blocks, security groups, and network ACLs, with the exact rules that determine what traffic can flow where.
How a Virtual Private Cloud isolates and routes traffic — covering public vs private subnets, internet gateways, NAT gateways, CIDR blocks, security groups, and network ACLs, with the exact rules that determine what traffic can flow where.
Lesson outline
A Virtual Private Cloud (VPC) is a logically isolated section of a cloud provider's network where you launch resources. Without a VPC, every EC2 instance, database, and container would sit on a flat shared network reachable by anyone. The VPC gives you a private address space (CIDR block), network segmentation via subnets, and control over ingress and egress traffic.
Think of a VPC as a private office building. The building has one address on the street (your CIDR block), multiple floors (subnets), a front door that faces the street (internet gateway), a secure internal mail room for outbound packages (NAT gateway), ID badge readers on each room (security groups), and floor-level security checkpoints (network ACLs).
CIDR notation crash course
10.0.0.0/16 means the first 16 bits are fixed, giving you 65,536 addresses (10.0.0.0 to 10.0.255.255). A /24 subnet has 256 addresses. AWS reserves 5 addresses in every subnet (first 4 + last 1), so a /24 gives you 251 usable IPs. For a production VPC, start with a /16 to avoid address exhaustion as you add subnets and services.
| Component | What it does | Analogy |
|---|---|---|
| VPC | Private address space for all your resources | The entire office building |
| Subnet | Segment of the VPC CIDR in a single AZ | A floor of the building |
| Internet Gateway | Allows bidirectional public internet traffic | The front door facing the street |
| NAT Gateway | Allows private resources to reach internet (outbound only) | The internal mail room — sends packages out, never lets strangers in |
| Route Table | Tells each subnet where to send traffic | The building's internal directory and exit signs |
| Security Group | Stateful firewall at the resource level (EC2, RDS) | ID badge reader on each office door |
| Network ACL | Stateless firewall at the subnet level | Security checkpoint at each floor entrance |
The most important design decision in a VPC is which subnets are public (internet-reachable) and which are private (internal-only). This single decision determines what your architecture's attack surface looks like.
Public subnet characteristics
Private subnet characteristics
The three-tier subnet pattern
A production VPC should have at minimum three subnet tiers per AZ: (1) Public subnets for load balancers and NAT gateways, (2) Application subnets (private) for ECS tasks, Lambda, EC2 app servers, (3) Data subnets (private, no NAT route) for RDS, ElastiCache, OpenSearch. Data subnets should not even have internet access via NAT — they only need VPC-internal routes. This limits blast radius if an app server is compromised.
NAT Gateway costs add up fast
AWS NAT Gateway costs $0.045/hour per gateway (~$32/month) plus $0.045 per GB of data processed. A single NAT Gateway processing 1 TB/month adds $45 to your bill — every month. In a multi-AZ setup with one NAT Gateway per AZ (recommended for resilience), that is $96/month before data charges. Use VPC endpoints for S3 and DynamoDB to avoid NAT charges for traffic that never needs to leave AWS.
1# Inspect a subnet's route table to determine if it is public or privateThe route table destination 0.0.0.0/0 pointing to an IGW is what defines a public subnet2aws ec2 describe-route-tables \3--filters "Name=association.subnet-id,Values=subnet-0abc123" \4--query 'RouteTables[].Routes[].{Dest:DestinationCidrBlock,Target:GatewayId}' \5--output table67# A public subnet shows: 0.0.0.0/0 -> igw-xxxxxxxxx8# A private subnet shows: 0.0.0.0/0 -> nat-xxxxxxxxx (or nothing)9VPC endpoints for S3 and DynamoDB bypass the NAT Gateway — significant cost saving10# List all VPC endpoints (avoid paying NAT fees for S3/DynamoDB)11aws ec2 describe-vpc-endpoints \12--filters "Name=vpc-id,Values=vpc-0abc123" \13--query 'VpcEndpoints[].{Service:ServiceName,Type:VpcEndpointType,State:State}'
AWS gives you two layers of network security: security groups (resource-level, stateful) and network ACLs (subnet-level, stateless). Most engineers understand security groups but misunderstand NACLs, which causes subtle connectivity bugs.
| Feature | Security Group | Network ACL |
|---|---|---|
| Applies to | Individual resources (EC2, RDS, Lambda ENI) | Entire subnet (all resources in it) |
| Statefulness | Stateful — return traffic automatically allowed | Stateless — must explicitly allow both inbound AND outbound |
| Rule evaluation | All rules evaluated; most permissive wins | Rules evaluated in order by number; first match wins |
| Default (new resource) | Deny all inbound, allow all outbound | Allow all inbound and outbound (default NACL) |
| Use case | Primary access control for all resources | Additional layer of defence; subnet-level blocking |
The stateless NACL trap
If you add a NACL rule to allow inbound TCP port 443 but forget to add the outbound rule for ephemeral ports (1024–65535), all HTTPS requests will silently hang. The SYN packet arrives (inbound 443 allowed), the server responds, but the response packet on an ephemeral port is blocked by the outbound NACL. Security groups do not have this problem because they are stateful. NACLs are most useful for blocking specific IP ranges at the subnet level, not for fine-grained port control.
Security group chaining is more secure than IP-based rules
Instead of allowing inbound port 5432 from 10.0.1.0/24 (a subnet CIDR), allow inbound port 5432 from the security group ID of your application servers (sg-0abc123). This means only resources in that specific security group can connect — not any IP in the subnet. If an attacker compromises a different resource on the same subnet, it still cannot reach your database.
Route tables are the nervous system of a VPC. Every subnet is associated with exactly one route table. When a packet leaves a resource, the VPC router looks up the destination IP in the route table and forwards it to the most specific matching route target.
How a packet travels from an app server to the internet
01
App server (in private subnet 10.0.2.0/24) initiates a connection to 151.101.1.140 (GitHub).
02
VPC router checks the route table for subnet 10.0.2.0/24. Finds: 10.0.0.0/16 → local; 0.0.0.0/0 → nat-0xyz.
03
Packet is forwarded to the NAT Gateway in the public subnet.
04
NAT Gateway replaces the source IP (10.0.2.45) with its own public Elastic IP and forwards the packet to the Internet Gateway.
05
Internet Gateway routes the packet to the public internet.
06
Return traffic comes back to the NAT Gateway's Elastic IP; NAT Gateway translates it back to 10.0.2.45 and delivers it to the app server.
App server (in private subnet 10.0.2.0/24) initiates a connection to 151.101.1.140 (GitHub).
VPC router checks the route table for subnet 10.0.2.0/24. Finds: 10.0.0.0/16 → local; 0.0.0.0/0 → nat-0xyz.
Packet is forwarded to the NAT Gateway in the public subnet.
NAT Gateway replaces the source IP (10.0.2.45) with its own public Elastic IP and forwards the packet to the Internet Gateway.
Internet Gateway routes the packet to the public internet.
Return traffic comes back to the NAT Gateway's Elastic IP; NAT Gateway translates it back to 10.0.2.45 and delivers it to the app server.
The VPC local route always wins
Every VPC route table has an implicit local route (e.g. 10.0.0.0/16 → local) that cannot be deleted or overridden. Traffic between resources in the same VPC always uses this local route, regardless of security group rules. Security groups control whether the traffic is accepted, but routing within the VPC always works — the firewall is not the router.
Appears in cloud engineer, DevOps engineer, and solutions architect interviews as both direct questions and embedded in system design problems. "Design a secure VPC for a fintech application" is a common prompt that tests subnet design, security layering, and connectivity patterns.
Common questions:
Try this question: How many AZs are required? What are the egress traffic volumes (affects NAT cost)? Are there any on-premises connectivity requirements (Direct Connect, VPN)? What compliance frameworks apply (affects subnet isolation requirements)?
Strong answer: Draws the three-tier subnet pattern unprompted. Recommends security group chaining over CIDR-based rules. Mentions AWS Config rules for continuous compliance. Raises VPC endpoint cost optimisation without prompting.
Red flags: Thinks a subnet is "public" just because it's labelled that way. Confuses security groups (stateful, resource-level) with NACLs (stateless, subnet-level). Cannot explain why a NAT Gateway allows outbound but not inbound traffic.
Scenario · E-commerce startup
Step 1 of 3
You are a cloud engineer at a fast-growing e-commerce startup. The team just deployed a new microservice architecture on AWS. The frontend application in a public subnet needs to reach an internal payment service EC2 instance in a private subnet, which in turn needs to reach a PostgreSQL RDS instance. The devs say "nothing can connect to anything." You need to diagnose and fix this systematically.
The frontend app server (in public subnet 10.0.1.0/24) cannot reach the payment service EC2 (in private subnet 10.0.2.0/24, port 8080). You check the payment service security group and see: Inbound: allow port 8080 from 10.0.2.0/24.
What is wrong with this security group rule?
Match VPC component to its correct behaviour
0 / 7 matched
Match each VPC component or concept on the left with its defining characteristic on the right.
Quick check · VPC Fundamentals: Subnets, Route Tables & Gateways
1 / 5
Key takeaways
An engineer tells you "the subnet is public so resources in it are reachable from the internet." Is this correct?
Not entirely. A subnet being "public" (route table has 0.0.0.0/0 → IGW) is necessary but not sufficient. The resource also needs a public IP, AND the security group must allow inbound traffic on the relevant port. All three conditions must be true. The security group is the most important control — even a public subnet resource with a public IP is unreachable if the SG has no inbound allow rules.
Why does NACL statelessness cause the "HTTPS works inbound but responses never arrive" bug?
NACLs are stateless: they evaluate every packet independently, both directions. If you allow inbound TCP 443 in a NACL but forget to allow outbound traffic on ephemeral ports (1024–65535), the TCP handshake response packets are blocked on the way out. The client sees a SYN-ACK that never arrives. Security groups do not have this problem — they automatically allow return traffic for established connections.
💡 Analogy
Your VPC is a private office building. The building has one street address (your CIDR block like 10.0.0.0/16). Inside, each floor is a subnet. The front door with a security desk is the Internet Gateway — it faces the street and allows visitors in and out. The internal mail room is the NAT Gateway — it sends packages out to the street on behalf of staff on private floors, but strangers cannot use it to get in. Every office room has an ID badge reader (security group) that checks who is allowed to enter. Each floor has a checkpoint at the stairwell (network ACL) that can block entire categories of visitor before they even reach a room.
⚡ Core Idea
A subnet is public if and only if its route table has a 0.0.0.0/0 route pointing to an Internet Gateway. Security groups are stateful resource-level firewalls. Network ACLs are stateless subnet-level firewalls. These three controls together define what traffic can flow where inside your VPC.
🎯 Why It Matters
VPC misconfiguration is the most common cause of accidental cloud data exposure. A database in a public subnet with a permissive security group rule is reachable from the entire internet. Understanding exactly what makes a subnet public (route table, not just the label "public") and how security groups layer with NACLs is foundational knowledge for any cloud engineer.
Ready to see how this works in the cloud?
Switch to Career Paths for structured paths (e.g. Developer, DevOps) and provider-specific lessons.
View role-based pathsSign in to track your progress and mark lessons complete.
Questions? Discuss in the community or start a thread below.
Join DiscordSign in to start or join a thread.