Amazon VPC: Building an Isolated Network Layer That Actually Makes Sense
Every AWS account gets a default VPC in each region. Most teams outgrow it quickly — the default VPC is configured for convenience, not for production security. Building your own VPC with deliberate CIDR planning, proper subnet segmentation, and layered security controls is a foundational skill for anyone designing AWS architectures.
A VPC is a logically isolated network that you define within an AWS region. You choose the IP address range, how to divide it into subnets, which subnets can reach the internet, and who can talk to what.
VPC and CIDR Planning
A CIDR block defines your VPC’s IP address space. Choosing it carefully matters because:
- You cannot resize a VPC CIDR after creation (you can add secondary CIDRs)
- VPCs you peer with must have non-overlapping CIDRs
Common choices:
10.0.0.0/16— 65,536 addresses, most common for production172.16.0.0/12— large enough for multi-region architectures10.0.0.0/8— maximum AWS allows per VPC
Avoid 192.168.0.0/16 (commonly used by home routers, causes conflicts in VPN scenarios).
For organisations with multiple VPCs across environments and regions, maintain a CIDR allocation registry:
Environment Region VPC CIDR─────────────────────────────────────────────Production us-east-1 10.0.0.0/16Production eu-west-1 10.1.0.0/16Staging us-east-1 10.10.0.0/16Development us-east-1 10.20.0.0/16Non-overlapping CIDRs allow VPC peering and Transit Gateway attachment across all environments without routing conflicts.
Subnet Architecture
Subnets divide your VPC IP space by function and availability zone. The key distinction is public vs private:
VPC: 10.0.0.0/16│├── AZ us-east-1a│ ├── Public subnet: 10.0.1.0/24 (256 IPs)│ ├── Private subnet: 10.0.11.0/24 (256 IPs)│ └── Isolated subnet: 10.0.21.0/24 (256 IPs)│└── AZ us-east-1b ├── Public subnet: 10.0.2.0/24 (256 IPs) ├── Private subnet: 10.0.12.0/24 (256 IPs) └── Isolated subnet: 10.0.22.0/24 (256 IPs)Public subnets have a route to the Internet Gateway. Resources here can have public IPs and receive inbound internet traffic (if security groups allow). Load balancers and bastion hosts go here.
Private subnets have no direct internet route. Resources go outbound via NAT Gateway (in the public subnet). Application servers and ECS tasks go here.
Isolated subnets have no internet access at all, not even outbound. Databases that should never touch the internet go here.
aws ec2 create-vpc --cidr-block 10.0.0.0/16 \ --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=production-vpc}]'
# Public subnet in AZ-1aaws ec2 create-subnet \ --vpc-id vpc-0abc123 \ --cidr-block 10.0.1.0/24 \ --availability-zone us-east-1a \ --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=public-1a}]'
# Private subnet in AZ-1aaws ec2 create-subnet \ --vpc-id vpc-0abc123 \ --cidr-block 10.0.11.0/24 \ --availability-zone us-east-1a \ --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-1a}]'Note: AWS reserves 5 IP addresses in each subnet (first 4 and the last). A /24 subnet has 256 total, 251 usable.
Route Tables
Route tables determine where traffic from a subnet goes. Each subnet must be associated with exactly one route table.
Public route table:
Destination Target─────────────────────────────────────10.0.0.0/16 local0.0.0.0/0 igw-0abc123 ← Internet GatewayPrivate route table (with NAT):
Destination Target─────────────────────────────────────10.0.0.0/16 local0.0.0.0/0 nat-0abc123 ← NAT Gateway (in public subnet)Isolated route table:
Destination Target─────────────────────────────────────10.0.0.0/16 localOnly the local route — no internet access in any direction.
Security Groups vs Network ACLs
Both control traffic but work at different levels:
┌─────────────────────────────────────────────────────────────────┐│ Security Layer Comparison ││ ││ Feature Security Group Network ACL ││ ──────────────────────────────────────────────────────────── ││ Applied to Instance / ENI Subnet ││ State Stateful Stateless ││ Rule direction Allow only Allow & Deny ││ Rule evaluation All rules evaluated Rules evaluated ││ at once in order by # ││ Default Deny all in, Allow all in/out ││ Allow all out │└─────────────────────────────────────────────────────────────────┘Security groups are stateful: If you allow TCP 80 inbound, the response traffic is automatically allowed outbound — you do not write a separate outbound rule.
NACLs are stateless: You must write both an inbound rule and an outbound rule. If you allow HTTP on port 80 inbound, you must also allow ephemeral ports (1024-65535) outbound for the response traffic.
For most architectures, security groups are the primary security control. NACLs are used for additional subnet-level blocking — for example, to block a specific IP range at the subnet level regardless of which instance it targets.
VPC Peering
VPC peering connects two VPCs so that resources in each can communicate using private IP addresses, as if they are in the same network. No traffic crosses the internet.
VPC A (10.0.0.0/16) ──── Peering Connection ──── VPC B (10.1.0.0/16)Each VPC needs route table entries pointing the other VPC’s CIDR at the peering connection, and security groups must allow the traffic.
# Request peeringaws ec2 create-vpc-peering-connection \ --vpc-id vpc-0abc123 \ --peer-vpc-id vpc-0def456
# Accept peering (in the other account/region if cross-account)aws ec2 accept-vpc-peering-connection \ --vpc-peering-connection-id pcx-0ghi789
# Add routes (in both VPCs)aws ec2 create-route \ --route-table-id rtb-0abc123 \ --destination-cidr-block 10.1.0.0/16 \ --vpc-peering-connection-id pcx-0ghi789VPC peering is not transitive. If A peers with B and B peers with C, A cannot reach C through B. For hub-and-spoke architectures with many VPCs, Transit Gateway is better.
VPC Endpoints
VPC Endpoints let traffic from your VPC reach AWS services without going through the internet or NAT Gateway. Two types:
Gateway Endpoints (for S3 and DynamoDB): Free. You add an entry to a route table pointing the service prefix list at the endpoint.
Interface Endpoints (for most other AWS services): Create an ENI in your subnet with a private IP. Traffic to the service goes to that ENI. Costs per hour and per GB processed.
# Create S3 gateway endpoint (free)aws ec2 create-vpc-endpoint \ --vpc-id vpc-0abc123 \ --service-name com.amazonaws.us-east-1.s3 \ --route-table-ids rtb-private-0abc123
# Create Secrets Manager interface endpointaws ec2 create-vpc-endpoint \ --vpc-id vpc-0abc123 \ --vpc-endpoint-type Interface \ --service-name com.amazonaws.us-east-1.secretsmanager \ --subnet-ids subnet-private-0a1b2c subnet-private-0d4e5f \ --security-group-ids sg-endpointsFor Lambda functions or ECS tasks in private subnets that call AWS APIs, interface endpoints eliminate the need for a NAT Gateway just for AWS API calls.
AWS PrivateLink
PrivateLink is a service that lets you expose your application to other VPCs as a private endpoint, without peering the VPCs or exposing anything to the internet.
Consumer VPC Provider VPC ┌──────────┐ Interface ┌──────────────┐ │ Client ├──────Endpoint────►│ NLB → App │ └──────────┘ (private IP) └──────────────┘AWS uses PrivateLink for many of its own services. SaaS companies use it to offer their services to customers who want private connectivity without peering.
VPC Flow Logs
Flow logs capture metadata about IP traffic through your VPC, subnets, or network interfaces. They do not capture packet content, but they capture source IP, destination IP, port, protocol, action (ACCEPT or REJECT), and byte count.
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::123456789012:role/flow-logs-roleFlow logs are essential for:
- Debugging connection failures (is traffic hitting the security group? NACL?)
- Security investigations (which IP was communicating with this instance at 2am?)
- Network performance analysis (which flows have the most bytes?)
Common Interview Questions
Q: What is the difference between a security group and a NACL? Security groups are stateful, instance-level firewalls. NACLs are stateless, subnet-level firewalls. Security groups only allow traffic (no explicit deny). NACLs support both allow and deny rules evaluated in number order. In practice, security groups are the primary control; NACLs add an additional layer.
Q: What is VPC peering and what are its limitations? Peering connects two VPCs for private communication. Limitations: not transitive (A-B-C does not mean A can reach C), each pair needs its own peering connection, CIDR blocks must not overlap, no edge-to-edge routing (cannot use peering to route through a VPN or Direct Connect in the other VPC).
Q: What is the difference between a Gateway Endpoint and an Interface Endpoint? Gateway Endpoints are free, support only S3 and DynamoDB, and work by adding a route table entry. Interface Endpoints create an ENI in your subnet, cost per hour and per GB, and support most AWS services. Gateway Endpoints have no throughput limit; Interface Endpoints are limited by the ENI bandwidth.
Q: Can two VPCs have overlapping CIDR blocks and still be peered? No. Peered VPCs must have non-overlapping CIDRs. This is one reason careful CIDR planning at the start of an AWS deployment is important.