🌐 AWS VPC — Complete Reference Guide
What is a VPC? Your own isolated private network inside AWS. Think of it as your private data center in the cloud. Nothing gets in or out unless you explicitly allow it.
📌 Table of Contents
🧠 Core Concepts
A VPC gives you full control over your virtual networking environment including IP address ranges, subnets, route tables, and gateways.
Key facts:
-
A VPC exists within a single AWS Region
-
A VPC can span multiple Availability Zones (AZs)
-
Each AWS account gets a default VPC per region (ready to use out of the box)
-
The VPC itself is free — but some components (NAT Gateway, VPC Endpoints) cost money
-
You can create multiple VPCs per region (default limit: 5, can request increase)
🏗 VPC Architecture Diagram
Internet
│
▼
┌──────────────────────────────────────────────────────────┐
│ VPC (172.16.0.0/16) │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ PUBLIC SUBNET (172.16.1.0/24) │ │
│ │ - Has route to Internet Gateway │ │
│ │ - Resources CAN have public IPs │ │
│ │ - ALB (Load Balancer) lives here │ │
│ │ - ECS tasks live here (if no NAT Gateway) │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ▼ (security group allows) │
│ ┌──────────────────────────────────────────────────┐ │
│ │ PRIVATE SUBNET (172.16.2.0/24) │ │
│ │ - NO route to Internet Gateway │ │
│ │ - Resources CANNOT reach internet directly │ │
│ │ - RDS databases live here │ │
│ │ - Redis / ElastiCache lives here │ │
│ └──────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
🔑 Key Components Deep Dive
| Component | What It Does | Analogy |
| VPC | Your isolated network in AWS | Your private data center |
| Subnet | A range of IPs within the VPC, in one AZ | Rooms in your data center |
| Internet Gateway | Connects VPC to the public internet | The front door |
| NAT Gateway | Lets private resources access internet (outbound only) | A one-way mail slot |
| Route Table | Defines where traffic goes | Road signs |
| Security Group | Stateful firewall per resource (instance-level) | A personal bodyguard |
| NACL | Stateless firewall per subnet | A building security gate |
| VPC Endpoint | Private connection to AWS services without internet | Internal hallway to another building |
| Elastic IP | A static public IPv4 address | A fixed phone number |
🔢 CIDR Blocks & IP Addressing
CIDR (Classless Inter-Domain Routing) defines the IP range for your VPC.
Common VPC CIDR blocks:
| CIDR Block | IP Range | Total IPs | Use Case |
10.0.0.0/16 | 10.0.0.0 – 10.0.255.255 | 65,536 | Large production VPC |
172.16.0.0/16 | 172.16.0.0 – 172.16.255.255 | 65,536 | Standard VPC |
192.168.0.0/16 | 192.168.0.0 – 192.168.255.255 | 65,536 | Smaller environments |
10.0.0.0/24 | 10.0.0.0 – 10.0.0.255 | 256 | Single small subnet |
Quick CIDR math:
-
/16= 65,536 IPs -
/20= 4,096 IPs -
/24= 256 IPs -
/28= 16 IPs (smallest allowed in AWS)
Rules:
-
VPC CIDR range:
/16(largest) to/28(smallest) -
AWS reserves 5 IPs in every subnet (first 4 + last 1)
-
Don't overlap CIDR ranges if you plan to peer VPCs or connect on-premises
🏠 Subnets
A subnet is a range of IPs within your VPC, placed in one specific Availability Zone.
Public vs Private — the only real difference
| Feature | Public Subnet | Private Subnet |
| Route to Internet Gateway | ✅ Yes | ❌ No |
| Resources get public IPs | ✅ Can | ❌ Cannot |
| Direct internet access | ✅ Yes | ❌ No (needs NAT) |
| Typical residents | ALB, Bastion hosts, web servers | Databases, caches, app servers |
Key insight: What makes a subnet "public" or "private" is only the route table — whether it has a route to the Internet Gateway. Nothing else.
Multi-AZ subnets for high availability
Always create subnets across at least 2 AZs:
VPC (10.0.0.0/16)
├── Public Subnet AZ-a (10.0.1.0/24)
├── Public Subnet AZ-b (10.0.2.0/24)
├── Private Subnet AZ-a (10.0.3.0/24)
└── Private Subnet AZ-b (10.0.4.0/24)
This way, if one AZ goes down, your app keeps running in the other.
🚪 Internet Gateway (IGW)
-
Connects your VPC to the public internet
-
One per VPC (you can only attach one IGW to a VPC)
-
Horizontally scaled, redundant, highly available — AWS manages it
-
Free — no hourly charge or data processing fee
-
Without it, nothing in your VPC can reach (or be reached from) the internet
To make a resource internet-accessible you need ALL of these:
-
IGW attached to the VPC
-
Route table entry pointing
0.0.0.0/0→ IGW -
Resource has a public IP or Elastic IP
-
Security group allows the traffic
🔄 NAT Gateway
Allows resources in private subnets to access the internet outbound only (e.g., to download updates, pull Docker images).
Key details:
-
Lives in a public subnet
-
Requires an Elastic IP
-
Costs ~$32/month + $0.045/GB data processed
-
One per AZ for high availability (so 2-3 AZs = $64–96/month just for NAT)
-
Managed by AWS — no patching needed
Alternative to save money: Place resources in public subnets with public IPs instead of using a NAT Gateway. This is less secure but saves ~$100+/month. This is what many dev/staging environments do.
🗺 Route Tables
Every subnet is associated with a route table. The route table tells traffic where to go.
Public subnet route table
Destination → Target
172.16.0.0/16 → local (stay inside VPC)
0.0.0.0/0 → igw-xxxx (internet gateway)
Private subnet route table (with NAT)
Destination → Target
172.16.0.0/16 → local (stay inside VPC)
0.0.0.0/0 → nat-xxxx (NAT gateway)
Private subnet route table (no NAT, fully isolated)
Destination → Target
172.16.0.0/16 → local (stay inside VPC)
The
localroute is automatic and cannot be removed. It ensures all VPC-internal traffic stays internal.
🛡 Security Groups
The most important security control in AWS. Stateful firewalls attached to individual resources (EC2, RDS, ECS, ALB, etc.).
Key properties
| Property | Security Group |
| Level | Resource (instance) level |
| Stateful? | ✅ Yes — if inbound is allowed, response is auto-allowed |
| Default behavior | Deny all inbound, allow all outbound |
| Rules | Allow rules only (no deny rules) |
| Can reference | Other security groups, CIDR blocks, or prefix lists |
Security group chaining (best practice)
Instead of using IP addresses, security groups reference other security groups:
Internet → ALB SG (allows port 80/443 from 0.0.0.0/0)
│
▼
ECS SG (allows port 5000 from ALB SG only)
│
▼
RDS SG (allows port 5432 from ECS SG only)
Redis SG (allows port 6379 from ECS SG only)
Why this matters: If you add a new ECS task, it automatically gets access to RDS because it has the ECS security group attached. No need to update IP addresses anywhere.
Common port reference
| Service | Port | Protocol |
| HTTP | 80 | TCP |
| HTTPS | 443 | TCP |
| SSH | 22 | TCP |
| PostgreSQL | 5432 | TCP |
| MySQL | 3306 | TCP |
| Redis | 6379 | TCP |
| Custom app (e.g., Redash) | 5000 | TCP |
🧱 Network ACLs (NACLs)
A second layer of security at the subnet level.
| Property | NACL | Security Group |
| Level | Subnet level | Resource level |
| Stateful? | ❌ No — must allow both inbound AND outbound | ✅ Yes |
| Default behavior | Allow all (default NACL) | Deny all inbound |
| Rule type | Allow AND deny rules | Allow only |
| Evaluation | Rules processed in number order | All rules evaluated |
In practice: Most people leave NACLs at default (allow all) and rely on security groups. NACLs are useful as a backup layer or for blocking specific IP addresses.
🔗 VPC Endpoints
Access AWS services without going through the internet. Traffic stays on AWS's private network.
Two types
| Type | Cost | Supports | How it works |
| Gateway Endpoint | Free | S3, DynamoDB only | Adds a route to your route table |
| Interface Endpoint | ~$7/month + data | Most other AWS services (ECR, Secrets Manager, CloudWatch, etc.) | Creates an ENI in your subnet |
When to use: If your resources are in a private subnet with no NAT Gateway, VPC Endpoints let them access AWS services like S3 or ECR without internet access.
🔀 VPC Peering & Transit Gateway
VPC Peering
-
Connects two VPCs so they can communicate using private IPs
-
Can peer across regions and across AWS accounts
-
Free (you only pay normal data transfer)
-
CIDR ranges cannot overlap
-
Gets messy with 3+ VPCs (every pair needs its own peering connection)
Transit Gateway
-
A central hub that connects multiple VPCs, VPNs, and on-premises networks
-
Much cleaner than peering when you have many VPCs
-
Costs ~$0.05/hour per attachment + data transfer
-
Best for organizations with 3+ VPCs
🔄 Traffic Flow Example (Redash Setup)
Here's how a user request flows through the VPC to reach Redash:
1. User browser → https://redash.yourdomain.com
│
2. DNS (Route 53) → resolves to ALB's public IP
│
3. Internet Gateway → allows traffic into VPC
│
4. ALB (public subnet) → SG allows 443 from 0.0.0.0/0
│ terminates SSL, forwards to target group
│
5. Target Group → routes to ECS task on port 5000
│
6. ECS Task (public subnet) → SG allows 5000 from ALB SG
│ runs Redash containers
│
├──→ RDS (private subnet) → SG allows 5432 from ECS SG
│ returns query results
│
└──→ Redis (private subnet) → SG allows 6379 from ECS SG
returns cached data
Why can ECS talk to RDS across different subnets? Because they're in the same VPC. The local route (172.16.0.0/16 → local) keeps all internal VPC traffic internal. Security groups then control which specific resources can communicate.
🏛 Common Architecture Patterns
Pattern 1: Simple (Dev/Staging) — No NAT Gateway
Internet → IGW → Public Subnet (ALB + ECS with public IPs)
│
Private Subnet (RDS, Redis)
-
Cost: ~$0/month for networking
-
Trade-off: ECS tasks have public IPs (slightly less secure)
Pattern 2: Standard (Production)
Internet → IGW → Public Subnet (ALB only)
│
Private Subnet (ECS tasks, app servers)
│ │
NAT Gateway VPC Endpoints
│ │
(outbound (AWS services
internet) privately)
│
Isolated Subnet (RDS, Redis)
-
Cost: ~$32–96/month for NAT
-
Benefit: No public IPs on compute resources
Pattern 3: Enterprise (Multi-VPC)
On-Premises ←→ Transit Gateway ←→ VPC-Prod
│ ←→ VPC-Staging
│ ←→ VPC-Dev
│ ←→ Shared Services VPC
-
Cost: Higher (Transit Gateway + multiple NATs)
-
Benefit: Full isolation between environments
💰 Cost Breakdown
| Component | Cost | Notes |
| VPC | Free | — |
| Subnets | Free | — |
| Internet Gateway | Free | — |
| Route Tables | Free | — |
| Security Groups | Free | — |
| NACLs | Free | — |
| Elastic IP (attached) | Free | Charged if NOT attached (~$3.65/month) |
| NAT Gateway | ~$32/month + $0.045/GB | Per AZ — multiply by number of AZs |
| Gateway VPC Endpoint (S3/DynamoDB) | Free | — |
| Interface VPC Endpoint | ~$7/month + $0.01/GB | Per endpoint, per AZ |
| VPC Peering | Free | Data transfer charges apply |
| Transit Gateway | ~$36/month per attachment | + $0.02/GB processed |
| Data transfer (cross-AZ) | $0.01/GB each way | Adds up with high traffic |
| Data transfer (out to internet) | ~$0.09/GB | First 100GB/month may be free |
✅ Best Practices Checklist
-
Plan CIDR ranges before creating VPCs — avoid overlap with other VPCs and on-prem
-
Use multiple AZs — minimum 2, ideally 3 for high availability
-
Put databases in private subnets — never expose RDS to the public internet
-
Use security group chaining — reference SGs instead of IP addresses
-
Enable VPC Flow Logs — for debugging and security auditing
-
Enable DNS hostnames + DNS resolution — needed for many AWS services
-
Use S3 Gateway Endpoint — it's free and avoids NAT data charges for S3 traffic
-
Tag everything — VPC, subnets, route tables, security groups
-
Use separate VPCs for production vs dev/staging
-
Use AWS Secrets Manager for database credentials — don't hardcode passwords
-
Set "Publicly Accessible" to false on RDS instances
-
Review security groups regularly — remove unused rules and overly broad access
❌ Common Mistakes & Troubleshooting
"I can't connect to my RDS from my laptop"
Why: RDS is in a private subnet, SG only allows traffic from ECS SG, and "Publicly Accessible" is false.
Fix: Use a bastion host, AWS Session Manager, or VPN to connect. Never make RDS publicly accessible in production.
"My ECS task can't pull Docker images"
Why: Task is in a private subnet with no internet access.
Fix: Either add a NAT Gateway, move to a public subnet with a public IP, or use VPC Endpoints for ECR.
"My security group rule isn't working"
Why: Common causes:
-
Wrong port number
-
Referenced wrong security group
-
Forgot outbound rule on NACL (NACLs are stateless!)
-
Resource doesn't have the SG attached
"My subnets ran out of IPs"
Why: Used too small a CIDR (e.g., /28 = only 11 usable IPs after AWS reserves 5).
Fix: Create a larger subnet. You can add secondary CIDR blocks to a VPC.
"Cross-AZ data transfer costs are high"
Why: Traffic between AZs costs $0.01/GB each direction.
Fix: Co-locate related resources in the same AZ where possible, or accept the cost for HA.
🔗 Useful Links & Resources
Official AWS Documentation
Learning Resources
Tools
-
Reachability Analyzer — debug connectivity issues between resources
-
VPC Flow Logs — see what traffic is hitting your resources
📝 Quick Reference Card
VPC = Your private network (Free)
Subnet = A room in your network (Free)
IGW = Front door to internet (Free)
NAT GW = One-way outbound door ($$$)
Route Table = Traffic signs (Free)
Security Group = Bodyguard per resource (Free, stateful)
NACL = Building security gate (Free, stateless)
VPC Endpoint = Internal tunnel to AWS (Free for S3/DynamoDB)
Public subnet = has route to IGW
Private subnet = no route to IGW
That's literally the only difference.
Last updated: March 2026