AWS VPC Architecture Explained: From Beginner to Pro
A comprehensive guide to Amazon Virtual Private Cloud (VPC) — CIDR math, public/private subnets, Internet & NAT Gateways, Security Groups vs NACLs, VPC Endpoints, and packet routing mechanics.
In cloud engineering, security and isolation begin at the network layer. Every server, database, load balancer, and serverless function you deploy in Amazon Web Services (AWS) lives inside a Virtual Private Cloud (VPC).
An incorrectly configured VPC can expose private database clusters directly to the public internet, cause silent packet drops, or incur thousands of dollars in unexpected NAT Gateway data transfer charges. In this deep dive, we break down AWS networking from first principles: calculating subnets with CIDR math, designing multi-AZ high-availability public/private layouts, mastering stateful vs stateless firewalls, tracing network packet traversals, and automating infrastructure using Terraform.
1. What Is an AWS VPC? Building the Core Mental Model
1.1 The Corporate Office Building Analogy
To understand a Virtual Private Cloud (VPC), imagine renting an entire corporate office building. The building perimeter represents your VPC — an isolated section of the AWS cloud reserved exclusively for your AWS account. Inside the building, you divide space into separate floors and secure departments representing Subnets.
The main reception desk is your Internet Gateway (IGW), allowing public visitors in and out of the public lobby. Private executive offices represent Private Subnets where sensitive databases reside. To allow executives in private offices to download software updates without exposing their offices to outside visitors, you install a one-way security exit door — a NAT Gateway. Individual office door keycards represent Security Groups, while the building perimeter guard posts represent Network Access Control Lists (NACLs).
Diagram: The basic architectural isolation inside an AWS Virtual Private Cloud.
Pitfall — Overlapping CIDR blocks during multi-VPC architecture planning: Assigning default `172.31.0.0/16` or `10.0.0.0/16` IP ranges to all your VPCs prevents future VPC Peering or Transit Gateway connections. IP routing requires non-overlapping CIDR blocks across peered networks. Always allocate distinct, non-overlapping IP blocks (e.g. `10.100.0.0/16` for Production, `10.200.0.0/16` for Staging).
2. CIDR Block Allocation & Subnetting Mathematics
2.1 Classless Inter-Domain Routing (CIDR) Notation
A VPC is defined by a primary IPv4 CIDR block (e.g., 10.0.0.0/16). CIDR notation consists of an IP address followed by a slash and a prefix mask length $N \in [16, 28]$ indicating how many bits are fixed for the network prefix.
The number of total IP addresses in a $/N$ CIDR block is calculated as:
For a /16 VPC block ($N=16$), the total address space contains $2^{16} = 65,536$ IP addresses ranging from 10.0.0.0 to 10.0.255.255. When you divide a /16 VPC into smaller /24 subnets ($N=24$), each subnet contains $2^{8} = 256$ total addresses.
2.2 The 5 Reserved AWS Subnet IP Addresses
In standard networking, 2 IP addresses per subnet are reserved (Network Address and Broadcast Address). However, AWS reserves 5 IP addresses in every subnet for internal infrastructure management:
10.0.1.0— Network Address (cannot be assigned to instances).10.0.1.1— Reserved by AWS for the VPC Router.10.0.1.2— Reserved by AWS for the VPC DNS Server (AmazonProvidedDNS).10.0.1.3— Reserved by AWS for future expansion.10.0.1.255— Network Broadcast Address (AWS VPC does not support broadcast).
Thus, the number of **usable host IP addresses** in an AWS subnet of size $/N$ is given by:
For a /24 subnet ($256$ total IPs), exactly $256 - 5 = 251$ IP addresses are usable for EC2 instances, containers, or RDS endpoints.
Pitfall — Subnet exhaustion in Kubernetes/EKS clusters: Provisioning small subnets (e.g. `/28` with only $16 - 5 = 11$ usable IPs) for Elastic Kubernetes Service (EKS) worker nodes quickly exhausts IP addresses because AWS CNI assigns a unique private IP to every single Pod running on an EC2 node. Use `/22` or `/20` subnets for container workloads.
3. Public vs Private Subnets & Internet Routing
3.1 What Makes a Subnet "Public"?
In AWS, subnets are technically identical in structure. What turns a subnet into a **Public Subnet** is its associated **Route Table**.
A subnet is classified as public if its Route Table contains a default route (0.0.0.0/0) pointing to an attached **Internet Gateway (IGW)**:
| Destination CIDR | Target Object | Routing Behavior |
|---|---|---|
| `10.0.0.0/16` | `local` | Routes packets internally within the VPC |
| `0.0.0.0/0` | `igw-0a1b2c3d4e5f` | Routes outbound traffic to the Public Internet |
3.2 Private Subnet Routing
A **Private Subnet** has a Route Table with NO route to an Internet Gateway. Instances inside private subnets receive only private IP addresses (e.g. 10.0.2.45) and are completely unreachable from external internet traffic.
3.3 Dual-Stack IPv6 Subnetting Mechanics
Modern AWS VPCs support **Dual-Stack** architecture, where subnets carry both IPv4 and IPv6 address ranges simultaneously. AWS allocates a fixed `/56` IPv6 CIDR block (providing $2^{72}$ addresses) to your VPC, from which you assign fixed `/64` subnets to each Availability Zone:
Unlike IPv4 where NAT Gateways perform translation, IPv6 uses globally unique public IP addresses for all instances. For private IPv6 workloads requiring outbound internet connectivity without inbound accessibility, AWS provides an **Egress-Only Internet Gateway (EOIGW)**, acting as a stateless one-way IPv6 firewall equivalent to a NAT device.
Pitfall — Forgetting Auto-Assign Public IPv4 on Public Subnets: Creating an EC2 instance in a public subnet without enabling `Auto-Assign Public IP` leaves the instance with only a private IP. Even with an Internet Gateway route present, the instance cannot send or receive internet traffic because external routers cannot route private RFC 1918 IPs.
4. Outbound Internet Access: NAT Gateways vs NAT Instances
4.1 One-Way Outbound Access for Private Workloads
Private instances (e.g. backend microservices, database clusters) often require outbound access to the internet to download security patches, pull Docker base images, or call third-party APIs (like Stripe or Twilio). However, they must remain protected against incoming connection requests.
A **NAT Gateway (Network Address Translation)** provides this one-way outbound translation. The NAT Gateway MUST be deployed inside a **Public Subnet** and assigned a static **Elastic IP (EIP)**. The Private Subnet's Route Table is configured with a default route pointing to the NAT Gateway:
4.2 NAT Gateway vs NAT Instance Architectural Comparison
Historical AWS architectures used EC2 instances running Linux NAT software (NAT Instances). Modern architectures use managed NAT Gateways:
| Feature | Managed NAT Gateway | Legacy NAT Instance |
|---|---|---|
| Management Overhead | Fully managed by AWS (No OS patches) | Self-managed EC2 Linux instance |
| Bandwidth Scaling | Scales automatically up to 100 Gbps | Limited by EC2 instance network capacity |
| High Availability | Redundant within the specific Availability Zone | Single point of failure unless scripted |
| Cost Profile | ~$32/mo per AZ + $0.045/GB processed | Cost of small t4g.nano instance |
Pitfall — Surprise NAT Gateway data processing charges: NAT Gateways charge per-GB data processing fees ($0.045/GB). If a private EC2 instance backs up terabytes of data to an Amazon S3 bucket via a NAT Gateway, data processing fees can run into thousands of dollars. Use a free S3 Gateway VPC Endpoint instead!
5. Stateful vs Stateless Security: Security Groups vs NACLs
5.1 Dual-Layer Firewall Architecture
AWS enforces network security through two complementary firewall layers: **Security Groups (SGs)** operating at the Elastic Network Interface (ENI) level, and **Network Access Control Lists (NACLs)** operating at the Subnet boundary.
5.2 TCP Connection State Tracking Mathematics
Why are Security Groups stateful while NACLs are stateless? The answer lies in Linux kernel `conntrack` connection tracking mechanics implemented inside AWS Nitro hypervisors. When a packet enters an Elastic Network Interface (ENI), the hypervisor checks its connection tracking table $\mathcal{T}_{\text{conn}}$:
If an inbound packet matches a Security Group `ALLOW` rule, the hypervisor inserts a new 5-tuple entry into $\mathcal{T}_{\text{conn}}$ marked as `ESTABLISHED`. When the instance sends a response packet back to the client, the hypervisor performs an $O(1)$ hash lookup in $\mathcal{T}_{\text{conn}}$. Because the tuple exists, the response packet is allowed out immediately without checking outbound rules.
However, connection tracking tables have finite capacity. On Nitro hypervisors, untracked security group rules (e.g. using `10.0.0.0/16` for both inbound and outbound) bypass connection tracking tables entirely, supporting higher packet-per-second throughput without table overflow risk.
5.3 Comparative Security Matrix
| Security Attribute | Security Group (SG) | Network ACL (NACL) |
|---|---|---|
| Enforcement Boundary | Instance / ENI Interface level | Subnet boundary level |
| State Behavior | Stateful (Return traffic automatically allowed) | Stateless (Inbound & Outbound rules required) |
| Rule Action Support | ALLOW rules only (Default deny all) | ALLOW and DENY rules supported |
| Rule Evaluation Order | All rules evaluated simultaneously | Evaluated in numbered order (lowest first) |
Pitfall — Ephemeral port blocking in custom NACLs: Because NACLs are stateless, allowing inbound HTTP traffic on port 80 requires explicitly allowing outbound return traffic on Ephemeral Ports (ports 1024–65535). Forgetting outbound ephemeral rules in custom NACLs causes connection timeouts on outbound requests.
6. Private Connections: VPC Endpoints & PrivateLink
6.1 Gateway Endpoints vs Interface Endpoints
By default, accessing AWS services like S3 or DynamoDB from EC2 requires sending traffic out over the internet or through a NAT Gateway. **VPC Endpoints** allow instances in private subnets to communicate privately with supported AWS services without using internet gateways, NAT devices, or VPN connections.
- Gateway Endpoints: Free route-table targets supported for Amazon S3 and DynamoDB. They inject a prefix-list route directly into your subnet Route Table.
- Interface Endpoints (AWS PrivateLink): Elastic Network Interfaces (ENIs) with private IP addresses created in your subnet. Powered by PrivateLink, they support S3, KMS, SQS, SNS, and custom private services.
6.2 Prefix-List Routing vs PrivateLink ENI Architecture
To understand how Gateway Endpoints avoid data processing charges, look at Route Table prefix-lists. When you create an S3 Gateway Endpoint, AWS automatically populates your Route Table with a dynamic prefix-list destination:
Traffic destined for S3 bypasses the default internet route completely, routing through internal AWS software-defined network (SDN) backplanes. Because no physical network interfaces or NAT instances are instantiated, AWS offers Gateway Endpoints free of charge.
In contrast, **Interface Endpoints (PrivateLink)** instantiate actual Elastic Network Interfaces (ENIs) inside your private subnets, consuming a private IP address per Availability Zone. Traffic destined for `kms.us-east-1.amazonaws.com` resolves via Amazon DNS to the private IP of the endpoint ENI (`10.0.2.88`). Traffic traverses private hypervisor cross-links directly to the AWS service infrastructure, providing high security and isolated data paths.
7. Advanced: Packet Flow Lifecycle Through a VPC Network
7.1 Step-by-Step Inbound Packet Traversal Trace
To understand AWS networking at a senior architect level, trace the step-by-step path of an HTTP GET packet originating from client IP 198.51.100.45 arriving at an EC2 instance in a public subnet:
Sequence Diagram: Packet lifecycle traversing AWS IGW, NACLs, Route Tables, and Security Groups.
8. Advanced: Infrastructure-as-Code Implementation in Terraform
8.1 Production-Ready Multi-AZ VPC Module
The following complete Terraform configuration provisions a production-grade VPC spanning 2 Availability Zones with Public/Private subnets, an Internet Gateway, a NAT Gateway, and Route Tables:
9. Performance & Cost Comparison of AWS Data Transfer Paths
The chart below compares network throughput and cost profiles across AWS data access patterns for private workloads:
10. Interactive: VPC Packet Route Simulator
Click "Send Request" to trace how an outbound request from a private EC2 instance traverses the NAT Gateway and Internet Gateway to reach the web:
11. Common Architectural Traps
11.1 The Single-AZ Disaster Pattern
Deploying all subnets within a single Availability Zone (e.g. `us-east-1a`) leaves your entire application vulnerable to AWS data center outages. Always distribute subnets across at least two Availability Zones (Multi-AZ architecture) to maintain high availability.
11.2 Misconfigured Security Group Self-References
When microservices inside the same VPC need to communicate with each other, developers often hardcode IP ranges in Security Groups. Instead, use **Security Group Chaining**: configure the database Security Group to allow inbound traffic on port 5432 directly from the Web Server Security Group ID (e.g. `sg-web-servers`).
Pitfall — Missing DNS Resolution in Peered VPCs: When peering two VPCs, hostname resolution for private IP addresses fails by default. You must explicitly enable `enableDnsHostnames` and `enableDnsSupport` on both VPCs and check "Allow DNS Resolution from Remote VPC" in the Peering Connection settings.
12. Frequently Asked Questions
Q1: What is the maximum CIDR block size allowed for an AWS VPC?
The maximum CIDR block size for a VPC is `/16` (65,536 IPs). The minimum size is `/28` (16 IPs).
Q2: Can I change the primary CIDR block of a VPC after creation?
You cannot modify an existing CIDR block, but you can associate up to 4 secondary IPv4 CIDR blocks to an existing VPC.
Q3: What is the difference between a Stateful and Stateless firewall?
Stateful firewalls (Security Groups) automatically track connection state: if inbound traffic is allowed, return outbound traffic is permitted automatically. Stateless firewalls (NACLs) evaluate inbound and outbound rules independently for every packet.
Q4: Why does S3 Gateway Endpoint not incur any data processing charges?
AWS Gateway Endpoints use internal VPC route table prefix-lists without involving physical ENIs or software proxies, making them free of charge.
Q5: What is the difference between VPC Peering and AWS Transit Gateway?
VPC Peering connects two VPCs in a point-to-point mesh ($O(N^2)$ complexity). Transit Gateway acts as a central hub-and-spoke router connecting hundreds of VPCs and on-premises networks cleanly.
Q6: Can an EC2 instance in a private subnet have a public IP address?
Yes, but without a route to an Internet Gateway (`0.0.0.0/0 -> igw-xxx`), the public IP is non-functional and un-routable from the public internet.
Q7: How many NAT Gateways should I deploy for high availability?
Deploy one NAT Gateway per Availability Zone. NAT Gateways are scoped to a single AZ; if that AZ fails, private subnets in other AZs using that NAT Gateway lose outbound connectivity.
Q8: How do I test if an AWS Security Group is blocking a port?
Use AWS VPC Reachability Analyzer or `nc -zvw3