Amazon VPC: Designing Isolated Network Architectures on AWS
A comprehensive guide to Amazon Virtual Private Cloud covering network design principles, CLI provisioning workflows, cost governance, and security hardening strategies
Every workload deployed on AWS operates within a network boundary, and Amazon VPC is that boundary. A Virtual Private Cloud provides a logically isolated section of the AWS cloud where you define your own IP address space, architect subnets across availability zones, configure route tables, and enforce granular traffic control at multiple layers. Without a deliberately designed VPC, your infrastructure lacks the segmentation necessary to isolate tiers, limit blast radius during incidents, and establish secure connectivity between cloud and on-premises environments.
The question is never whether to use a VPC — every EC2 instance, RDS database, and VPC-attached Lambda function requires one. The real question is how to design your VPC so that it scales predictably, remains cost-efficient, and enforces defense in depth from day one.
Key Concepts
| Concept | Description |
|---|---|
| CIDR Blocks | Classless Inter-Domain Routing notation defines IP ranges using the format 10.0.0.0/16. The number after the slash indicates the count of fixed bits — a lower number yields more addresses. A /16 block provides 65,536 IPs, a /20 provides 4,096, a /24 provides 256, and a /32 represents a single IP. AWS reserves 5 IPs per subnet: the first four and the last. |
| Subnets | Network segments within your VPC, classified as either public or private. Public subnets maintain a route to the Internet Gateway and host instances with public IPs. Private subnets lack direct internet access, though they may route outbound traffic through a NAT Gateway. |
| Route Tables | Routing configurations that determine where traffic is directed. The Main Route Table applies by default to all subnets lacking an explicit association. Custom Route Tables are manually associated with specific subnets. Typical entries include 10.0.0.0/16 → local and 0.0.0.0/0 → igw-xxx. |
| Internet Gateway | The gateway enabling bidirectional traffic between your VPC and the public internet. Each VPC supports exactly one IGW, which must be explicitly attached. Instances require public IPs to communicate through it. |
| NAT Gateway | Enables instances in private subnets to initiate outbound internet connections while preventing inbound connections from the internet. It must reside in a public subnet and requires an Elastic IP. Approximate cost: ~0.045/GB processed. |
| Security Groups | Stateful virtual firewalls operating at the instance level. Because they are stateful, return traffic is automatically permitted. They support only ALLOW rules — no DENY rules — and can reference other Security Groups as a source. Newly created Security Groups permit all egress by default. |
| Network ACLs | Stateless firewalls operating at the subnet level. Because they are stateless, you must explicitly allow traffic in both directions. They support both ALLOW and DENY rules. The default NACL permits all traffic. |
Essential CLI Commands
aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=my-vpc}]' \
--region sa-east-1aws ec2 create-subnet \
--vpc-id vpc-xxxxx \
--cidr-block 10.0.1.0/24 \
--availability-zone sa-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=public-subnet}]'aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=my-igw}]'aws ec2 attach-internet-gateway \
--internet-gateway-id igw-xxxxx \
--vpc-id vpc-xxxxxaws ec2 allocate-address --domain vpcaws ec2 create-nat-gateway \
--subnet-id subnet-xxxxx \
--allocation-id eipalloc-xxxxxaws ec2 create-route-table \
--vpc-id vpc-xxxxx \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=public-rt}]'aws ec2 create-route \
--route-table-id rtb-xxxxx \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id igw-xxxxxaws ec2 associate-route-table \
--route-table-id rtb-xxxxx \
--subnet-id subnet-xxxxxaws ec2 create-security-group \
--group-name my-sg \
--description "My security group" \
--vpc-id vpc-xxxxxaws ec2 authorize-security-group-ingress \
--group-id sg-xxxxx \
--protocol tcp \
--port 22 \
--cidr 203.0.113.0/24aws ec2 describe-vpcsaws ec2 describe-subnets \
--filters "Name=vpc-id,Values=vpc-xxxxx"aws ec2 describe-route-tables \
--filters "Name=vpc-id,Values=vpc-xxxxx"aws ec2 describe-internet-gateways \
--filters "Name=attachment.vpc-id,Values=vpc-xxxxx"aws ec2 describe-nat-gateways \
--filter "Name=vpc-id,Values=vpc-xxxxx"aws ec2 describe-security-groups \
--filters "Name=vpc-id,Values=vpc-xxxxx"aws ec2 describe-security-group-rules \
--filters "Name=group-id,Values=sg-xxxxx"aws ec2 modify-subnet-attribute \
--subnet-id subnet-xxxxx \
--map-public-ip-on-launchaws ec2 revoke-security-group-ingress \
--group-id sg-xxxxx \
--protocol tcp \
--port 22 \
--cidr 203.0.113.0/24VPC deletion requires removing all dependent resources first. Follow the order below to avoid dependency errors: NAT Gateway and Elastic IP first, then route table associations and route tables, then the Internet Gateway, then subnets and security groups, and finally the VPC itself.
aws ec2 delete-nat-gateway --nat-gateway-id nat-xxxxxaws ec2 release-address --allocation-id eipalloc-xxxxxaws ec2 disassociate-route-table --association-id rtbassoc-xxxxxaws ec2 delete-route-table --route-table-id rtb-xxxxxaws ec2 detach-internet-gateway \
--internet-gateway-id igw-xxxxx \
--vpc-id vpc-xxxxxaws ec2 delete-internet-gateway --internet-gateway-id igw-xxxxxaws ec2 delete-subnet --subnet-id subnet-xxxxxaws ec2 delete-security-group --group-id sg-xxxxxaws ec2 delete-vpc --vpc-id vpc-xxxxxArchitecture and Traffic Flows
Three-Tier VPC Architecture
Inbound and Outbound Traffic Flow
Subnet Selection Decision Flow
Best Practices
Security
Never add an internet route to the Main Route Table. Doing so silently exposes every subnet that lacks an explicit route table association — including subnets you intended to keep private.
- Deploy databases, application servers, and internal services in private subnets — only resources requiring direct internet ingress belong in public subnets
- Apply the principle of least privilege to Security Groups by restricting rules to only the necessary ports and specific source IP ranges
- Enable VPC Flow Logs to maintain an auditable record of all traffic entering and leaving your network interfaces
- Avoid the Default VPC in production — create custom VPCs with intentional CIDR planning and subnet segmentation
- Layer NACLs for defense in depth when regulatory or compliance requirements demand an additional stateless filtering boundary
Performance and High Availability
- Distribute subnets across multiple Availability Zones to ensure workloads survive a single-zone failure
- Size subnets generously — remember that AWS reserves 5 IPs per subnet, and plan for three to five times your current capacity
- Deploy VPC Endpoints for S3 and DynamoDB to eliminate NAT Gateway traffic, reducing both latency and data processing costs
Operational Excellence
Adopt a consistent naming convention such as vpc-prod-web, subnet-public-1a, and sg-bastion-prod. Pair this with a tagging strategy that includes Environment, Project, Owner, and CostCenter to enable cost attribution and automated governance.
- Manage all VPC infrastructure through code using Terraform or CloudFormation to ensure reproducibility and simplify disaster recovery
- Document your network design including CIDR allocations, route table logic, and peering relationships
- Use VPC Peering or Transit Gateway for inter-VPC communication rather than routing traffic over the public internet
- Deploy redundant NAT Gateways — one per Availability Zone in production environments — to prevent a single point of failure
Common Mistakes
Cost Considerations
VPC Resource Pricing
| Resource | Cost | Notes |
|---|---|---|
| VPC, Subnets, Route Tables, IGW | Free | No charge for these foundational resources |
| NAT Gateway | $0.045/hour | Approximately $32/month per NAT Gateway |
| NAT Gateway — Data Processing | $0.045/GB | Applies to all traffic traversing the NAT |
| Unassociated Elastic IP | $0.005/hour | Approximately $3.60/month per idle EIP |
| Elastic IP with running instance | Free | Only one free EIP per instance |
| VPC Peering — Data Transfer | $0.01/GB | Between Availability Zones in the same region |
| VPN Connection | $0.05/hour | Approximately $36/month per VPN |
| Transit Gateway | 0.02/GB | Preferred over VPC Peering when connecting many VPCs |
Free Tier Boundaries
| Resource | Free Tier Status |
|---|---|
| VPC, Subnets, Route Tables | Unlimited, no charge |
| Security Groups | Up to 2,500 per region, no charge |
| Internet Gateway | Unlimited, no charge |
| NAT Gateway | Not included — charges begin from the first hour |
| Elastic IPs | 5 per region, free only when associated with a running instance |
Cost Optimization Strategies
The single most impactful cost optimization for VPC networking is deploying VPC Endpoints for S3 and DynamoDB. This eliminates the $0.045/GB NAT Gateway data processing charge for what is often the highest-volume traffic in your account.
Eliminate idle NAT Gateways in non-production environments. In development and test accounts, schedule NAT Gateway deletion during off-hours and recreate them on demand using Lambda and EventBridge automation.
aws ec2 delete-nat-gateway --nat-gateway-id nat-xxxxxDeploy VPC Endpoints to bypass NAT for AWS service traffic. This reduces both latency and per-gigabyte processing fees.
aws ec2 create-vpc-endpoint \
--vpc-id vpc-xxxxx \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-xxxxxConsider NAT Instances for non-production workloads. A t3.nano instance at approximately 32/month NAT Gateway, though it demands manual management and delivers lower throughput.
Audit for orphaned Elastic IPs regularly. Unassociated EIPs accumulate charges silently.
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==`null`]'Monitor data transfer patterns through Cost Explorer by filtering on the "Data Transfer" usage type to identify your highest-volume consumers.
Integration with Other AWS Services
| AWS Service | VPC Integration | Typical Use Case |
|---|---|---|
| EC2 | Instances launch into specific subnets | Web and application servers distributed across public and private subnets |
| RDS | DB instances deployed in subnet groups for multi-AZ resilience | Database tier isolated in private subnets, unreachable from the internet |
| Lambda | Functions can execute inside a VPC | Accessing RDS or other private resources from serverless functions |
| ELB | Load balancers deployed in public or private subnets | ALB in a public subnet distributing traffic to EC2 instances in private subnets |
| S3 | Accessible via VPC Endpoint without traversing the internet | Applications in private subnets accessing S3 without a NAT Gateway |
| DynamoDB | Accessible via VPC Endpoint | Reduced latency and elimination of data transfer costs |
| API Gateway | Private API Gateway accessible only from within the VPC | Internal APIs that must not be exposed to the public internet |
| CloudFront | Origin can be an ALB residing in the VPC | CDN caching content from application servers inside the VPC |
| Direct Connect | Dedicated connection linking VPC to on-premises data centers | Hybrid cloud architectures requiring consistent, low-latency connectivity |
| VPN | Virtual Private Gateway attached to the VPC | Encrypted access from corporate offices to VPC resources |
| Route 53 | Private Hosted Zones for internal DNS resolution | Resolving internal service names such as db.internal.com |
| CloudWatch | VPC Flow Logs for comprehensive traffic monitoring | Debugging Security Group rules, detecting anomalous traffic patterns |
| IAM | Instance Profiles for EC2 instances within the VPC | Granting permissions to instances without embedding static credentials |
Additional Resources
Official Documentation
Whitepapers
- AWS Well-Architected Framework — Security Pillar
- Building a Scalable and Secure Multi-VPC AWS Network Infrastructure
- VPC Connectivity Options