AWS VPC Explained: The Complete Beginner’s Guide to Cloud Networking
What Problem Does VPC Actually Solve?
AWS VPC Explained: The Complete Beginner’s Guide to Cloud Networking
What Problem Does VPC Actually Solve?
Across this series, you’ve launched EC2 instances, stored objects in S3, run databases in RDS, and triggered Lambda functions. At no point did we ask: where do these things actually live, network-wise? How do they talk to each other? What stops a stranger on the internet from connecting directly to your database?
That’s the gap VPC fills.
When AWS runs your resources, they don’t float in some undifferentiated cloud space. They live inside a network — IP ranges, routing rules, gateways, firewalls — exactly like a traditional data center network, except defined entirely in software.
Amazon VPC (Virtual Private Cloud) is your own private, isolated network inside AWS. You define its IP address range, carve it into subnets, control what can reach the internet and what can’t, and decide exactly which resources can talk to which other resources.
Every EC2 instance, RDS database, and Lambda function (when configured to use one) that we’ve discussed in this series runs inside a VPC. We’ve referenced “private subnets” and “security groups” throughout — this post is where all of that finally gets explained from the ground up.
IP Addressing and CIDR: The Language of Networks
Before anything else, you need to be fluent in CIDR notation — the way network ranges are expressed. Everything in VPC is described this way, so this isn’t optional background; it’s the alphabet.
An IP address like 10.0.1.25 is a 32-bit number, usually written as four 8-bit numbers (0–255) separated by dots.
CIDR notation (10.0.0.0/16) describes a range of IP addresses. The number after the slash tells you how many bits are "fixed" (the network portion) versus how many bits are "flexible" (the host portion).
/16— first 16 bits fixed, last 16 bits flexible → 65,536 addresses (10.0.0.0to10.0.255.255)/24— first 24 bits fixed, last 8 bits flexible → 256 addresses (10.0.1.0to10.0.1.255)/28— first 28 bits fixed, last 4 bits flexible → 16 addresses
The smaller the number after the slash, the larger the range. This trips people up at first — /16 is bigger than /24, not smaller.
A practical rule of thumb: a VPC is commonly sized /16 (65,536 addresses — plenty of room to grow). Subnets within it are commonly sized /24 (256 addresses each) or smaller.
Private IP ranges
VPCs use private IP address ranges — defined by RFC 1918 — which are not routable on the public internet:
10.0.0.0/8(10.0.0.0 – 10.255.255.255)172.16.0.0/12(172.16.0.0 – 172.31.255.255)192.168.0.0/16(192.168.0.0 – 192.168.255.255)
This is why your home router uses 192.168.1.1 and your office network might use 10.0.0.0/8 — these ranges are reserved for private, internal use across the entire world. AWS VPCs typically use 10.0.0.0/16 by convention, but any RFC 1918 range works.
The VPC: Your Network Boundary
A VPC is a logically isolated section of AWS, scoped to a single region (spanning all of that region’s Availability Zones).
When you create a VPC, you specify its CIDR block — say, 10.0.0.0/16. This defines the total address space available inside it. Every resource you place in this VPC — EC2 instances, RDS databases, Lambda functions (when VPC-attached) — gets a private IP address from within this range.
Key facts about VPCs:
- Region-scoped, not global. A VPC in
us-east-1is entirely separate from a VPC ineu-west-1. To connect them, you need VPC Peering or Transit Gateway (more below). - Isolated by default. Nothing outside the VPC can reach anything inside it unless you explicitly allow it.
- Every AWS account gets a Default VPC in each region, pre-configured with public subnets and an internet gateway — convenient for getting started, but production workloads should use custom VPCs designed deliberately.
- You can have multiple VPCs per region (default soft limit: 5, adjustable).
A VPC by itself is just an address space — it doesn’t do anything until you add subnets.
Subnets: Carving Up the VPC
A subnet is a subdivision of your VPC’s CIDR range, tied to a single Availability Zone.
If your VPC is 10.0.0.0/16, you might carve it into:
10.0.0.0/24 — Public subnet, AZ-a (10.0.0.0 – 10.0.0.255)
10.0.1.0/24 — Public subnet, AZ-b (10.0.1.0 – 10.0.1.255)
10.0.10.0/24 — Private subnet, AZ-a (10.0.10.0 – 10.0.10.255)
10.0.11.0/24 — Private subnet, AZ-b (10.0.11.0 – 10.0.11.255)
10.0.20.0/24 — Private subnet, AZ-a (database tier)
10.0.21.0/24 — Private subnet, AZ-b (database tier)
Notice the pattern: every tier gets a subnet in at least two AZs. This is what makes Multi-AZ deployments possible — your RDS Multi-AZ standby, your Auto Scaling group’s second instance, your Aurora reader — they all need a subnet in a different AZ from the primary.
Public vs. Private: It’s All About the Route Table
Here’s a common misconception worth correcting directly: a subnet is not “public” or “private” because of some special flag you set. It’s public or private purely based on what its route table points to.
- A subnet whose route table sends internet-bound traffic (
0.0.0.0/0) to an Internet Gateway is a public subnet. - A subnet whose route table has no route to an Internet Gateway is a private subnet.
That’s the entire distinction. Same subnet construct, different routing.
Reserved addresses
Every subnet has 5 reserved IP addresses that you can’t assign to resources:
- Network address (first address)
- VPC router (first address + 1)
- DNS server (first address + 2)
- Reserved for future use (first address + 3)
- Broadcast address (last address)
This is why a /24 subnet (256 addresses) actually gives you only 251 usable addresses.
Route Tables: The Traffic Cop
A route table is a set of rules — routes — that determine where network traffic from your subnet is directed.
Every route table has a default, unremovable rule: traffic destined for addresses within the VPC’s CIDR range stays local — it routes directly within the VPC.
Destination Target
10.0.0.0/16 local ← always present, can't be removed
Beyond that default, you add routes for everything else. The most common addition: routing internet-bound traffic.
Destination Target
10.0.0.0/16 local
0.0.0.0/0 igw-0a1b2c3d ← internet gateway (makes this a public subnet)
Every subnet is associated with exactly one route table (though one route table can be associated with multiple subnets). If you don’t explicitly associate a subnet, it uses the VPC’s main route table.
Route tables are how you express network policy declaratively: “this subnet can reach the internet,” “this subnet can only reach our on-premises network via VPN,” “this subnet has no external routes at all.”
Internet Gateway: The Door to the Internet
An Internet Gateway (IGW) is a horizontally scaled, redundant VPC component that allows communication between resources in your VPC and the internet.
A VPC can have exactly one Internet Gateway attached. It performs two functions:
- Provides a target in route tables for internet-bound traffic
- Performs 1:1 NAT for instances with public IP addresses — translating between the instance’s private IP and its assigned public IP
Critically: attaching an IGW to a VPC does nothing by itself. A subnet only becomes “public” when its route table is explicitly updated to send 0.0.0.0/0 traffic to the IGW. This two-step requirement (attach IGW + update route table) is a deliberate safety measure — nothing becomes internet-facing by accident.
Even with an IGW route, an instance only receives internet traffic if it also has a public IP address and its security group allows the relevant traffic.
NAT Gateway: Outbound Internet for Private Resources
Here’s a scenario the IGW alone doesn’t solve: you have a private subnet (correctly, your database and application servers shouldn’t be publicly reachable). But your application servers still need outbound internet access — to download OS patches, call third-party APIs, or fetch packages.
This is what a NAT Gateway is for. It allows resources in a private subnet to initiate outbound connections to the internet, while preventing the internet from initiating connections back in.
The flow:
Private subnet instance → NAT Gateway (in a public subnet) → Internet Gateway → Internet
The NAT Gateway lives in a public subnet and has its own Elastic IP. Private subnet instances route their internet-bound traffic to the NAT Gateway via their route table:
Private subnet route table:
Destination Target
10.0.0.0/16 local
0.0.0.0/0 nat-0a1b2c3d ← NAT Gateway, not IGW
Traffic flows out through the NAT Gateway, gets translated to the NAT Gateway’s public IP, and goes out to the internet. Return traffic comes back to the NAT Gateway and is routed back to the originating private instance. But nothing on the internet can initiate a new connection into the private subnet — NAT only permits outbound-initiated traffic.
NAT Gateway is AWS-managed: highly available within a single AZ, scales automatically up to 100 Gbps, no patching required. You pay an hourly rate plus a per-GB data processing charge.
Important architectural detail: NAT Gateways are AZ-scoped. For true high availability, deploy one NAT Gateway per AZ — if you have private subnets in 3 AZs, deploy 3 NAT Gateways, each routing traffic for its own AZ’s private subnets. A single NAT Gateway in one AZ becomes a single point of failure (and a cross-AZ data transfer cost) for the other AZs.
NAT Instance is the older, manual alternative — a regular EC2 instance configured to perform NAT. Cheaper for very low traffic, but you manage patching, scaling, and availability yourself. Almost always, NAT Gateway is the right choice today.
Security Groups vs. Network ACLs: Two Layers of Firewall
VPC gives you two distinct firewall mechanisms, operating at different layers. Conflating them is one of the most common points of confusion for newcomers.
Security Groups (instance-level, stateful)
We covered these in the EC2 post: security groups attach to individual resources (EC2 instances, RDS databases, Lambda ENIs) and control inbound/outbound traffic.
- Stateful — if inbound traffic is allowed, the response is automatically allowed outbound, regardless of outbound rules.
- Allow rules only — you cannot create an explicit “deny” rule. Everything not explicitly allowed is implicitly denied.
- Evaluated as a whole — all rules across all applicable security groups are evaluated together; if any rule allows the traffic, it’s permitted.
Network ACLs (subnet-level, stateless)
A Network ACL (NACL) operates at the subnet boundary — it controls traffic entering or leaving an entire subnet, regardless of which specific instance the traffic is destined for.
- Stateless — an allowed inbound rule does not automatically allow the corresponding outbound response. You must explicitly create both inbound and outbound rules for two-way communication.
- Supports both Allow and Deny rules — unlike security groups, you can explicitly block specific IP ranges.
- Rules evaluated in order, by rule number — the lowest-numbered matching rule wins, and evaluation stops there. This is fundamentally different from security groups, where all matching rules are combined.
NACL Inbound Rules:
Rule # Type Protocol Port Source Allow/Deny
100 HTTP TCP 80 0.0.0.0/0 ALLOW
200 HTTPS TCP 443 0.0.0.0/0 ALLOW
300 SSH TCP 22 203.0.113.0/24 ALLOW
* ALL ALL ALL 0.0.0.0/0 DENY (default, unremovable)
Every VPC gets a default NACL that allows all inbound and outbound traffic — effectively a no-op until you customize it. Every subnet is associated with exactly one NACL (the default, unless you create and assign a custom one).
When to use which
In practice, most architectures rely primarily on security groups for day-to-day access control — they’re easier to reason about (stateful, allow-only, attached to the actual resource).
NACLs are typically used as a coarse, secondary layer — for example, explicitly blocking a known-malicious IP range at the subnet level, or as defense-in-depth for highly regulated environments that require network-layer controls independent of instance configuration.
Security Group NACL Operates at Instance/ENI level Subnet level State Stateful Stateless Rule types Allow only Allow and Deny Evaluation All rules combined First match wins, in order Default behavior Deny all inbound Allow all (default NACL)
VPC Endpoints: Reaching AWS Services Without the Internet
Here’s a subtle but important issue: when an EC2 instance in a private subnet calls the S3 API (s3.amazonaws.com), where does that traffic go? By default, it routes out through your NAT Gateway, through the Internet Gateway, across the public internet, to AWS's S3 service — even though S3 is itself an AWS service.
This has real costs (NAT Gateway data processing charges) and real exposure (the request technically traverses the public internet, even if encrypted).
VPC Endpoints let you connect privately to supported AWS services without traversing the internet at all.
Gateway Endpoints
Free, and the simplest type. Supported only for S3 and DynamoDB. A Gateway Endpoint adds an entry to your route table that directs traffic destined for that service directly to the service, over AWS’s internal network — bypassing the NAT Gateway and Internet Gateway entirely.
Private subnet route table (with S3 Gateway Endpoint):
Destination Target
10.0.0.0/16 local
pl-xxxxx (S3 prefix) vpce-0a1b2c3d ← Gateway Endpoint
0.0.0.0/0 nat-0a1b2c3d
Setting this up is a five-minute change that eliminates NAT data processing charges for S3/DynamoDB traffic and keeps that traffic entirely on AWS’s private network.
Interface Endpoints
For all other AWS services (Lambda, SNS, SQS, Secrets Manager, CloudWatch, Systems Manager, and dozens more), you use an Interface Endpoint — an Elastic Network Interface placed directly in your subnet, backed by AWS PrivateLink, with a private IP address.
Your application calls the service’s regular DNS name; with the endpoint’s private DNS option enabled, that DNS name resolves to the endpoint’s private IP instead of the public AWS endpoint. No code changes required — just infrastructure configuration.
Interface Endpoints have an hourly cost plus per-GB data processing — unlike the free Gateway Endpoints — so they’re typically deployed for services with meaningful traffic volume or for environments with strict no-internet-egress compliance requirements.
Connecting VPCs and Networks Together
A single VPC is often not the end of the story. Real organizations need to connect VPCs to each other, or to on-premises networks.
VPC Peering
A VPC Peering connection creates a direct, private network connection between two VPCs — they behave as if they’re on the same network, with traffic routed via private IP addresses.
- One-to-one connection — to connect 5 VPCs to each other, you’d need 10 peering connections (full mesh)
- Not transitive — if VPC A is peered with VPC B, and VPC B is peered with VPC C, A cannot reach C through B. Each pair needs its own direct peering connection.
- CIDR ranges must not overlap between peered VPCs
Good for: a small number of VPCs that need to communicate (e.g., a shared services VPC peered with a few application VPCs).
Transit Gateway
For anything beyond a handful of VPCs, Transit Gateway is the right tool. It acts as a central hub — a cloud router — that all your VPCs (and on-premises networks, via VPN or Direct Connect) attach to.
VPC A ─┐
VPC B ─┼─→ Transit Gateway ─→ On-premises (via VPN)
VPC C ─┘
Instead of a full mesh of peering connections (which becomes unmanageable at scale — 10 VPCs would need 45 peering connections), each VPC has a single attachment to the Transit Gateway. Transit Gateway route tables control which attachments can reach which other attachments — you can segment traffic (e.g., production VPCs can reach each other, but not development VPCs) all from one central place.
This is the standard pattern for organizations with many VPCs — separate VPCs per environment (dev/staging/prod), per team, or per application, all connected through a single Transit Gateway with clear routing policies.
Connecting to On-Premises Networks
Site-to-Site VPN — an encrypted IPsec tunnel over the public internet between your VPC and your on-premises network. Quick to set up (minutes), runs over the internet, so throughput and latency depend on internet conditions. Good for moderate traffic and quick connectivity needs.
AWS Direct Connect — a dedicated, private physical network connection from your data center to AWS, provisioned through a Direct Connect partner. Bypasses the public internet entirely. Higher throughput (up to 100 Gbps), consistent low latency, but takes weeks to provision and costs significantly more. Used by enterprises with serious, sustained hybrid-cloud traffic — large data migrations, latency-sensitive applications, regulatory requirements around not traversing the public internet.
Many enterprises run both: Direct Connect as the primary path, Site-to-Site VPN as an automatic failover if Direct Connect has an issue.
DNS in a VPC: Route 53 Resolver
Every VPC has a built-in DNS resolver (at the VPC’s base CIDR address + 2, e.g., 10.0.0.2), automatically handling:
- Resolution of public DNS names (
google.com) - Resolution of AWS service endpoints
- Resolution of private DNS names for resources in the VPC (when
enableDnsHostnamesandenableDnsSupportare enabled — both on by default)
For hybrid environments — where your VPC needs to resolve DNS names from your on-premises network, or your on-premises network needs to resolve names from your VPC’s private hosted zones — Route 53 Resolver provides inbound and outbound endpoints that bridge DNS resolution across the VPN or Direct Connect connection.
Private Hosted Zones (a Route 53 feature) let you create internal DNS records — db.internal.mycompany.com resolving to your RDS endpoint's private IP — visible only within associated VPCs, never exposed publicly.
VPC Flow Logs: Seeing What’s Actually Happening
VPC Flow Logs capture metadata about the IP traffic flowing through your VPC’s network interfaces — source/destination IP, ports, protocol, byte counts, and whether the traffic was accepted or rejected.
2 123456789012 eni-1235b8ca abc.def.gh.ij 172.31.16.21 20641 22 6 20 4249 1418530010 1418530070 ACCEPT OK
Flow Logs can be sent to CloudWatch Logs or S3, and can be enabled at the VPC, subnet, or individual network interface level.
This is your primary tool for:
- Troubleshooting connectivity issues — “why can’t my app reach the database?” Flow Logs show you whether the traffic was rejected, and at which point.
- Security analysis — identifying unexpected traffic patterns, potential port scans, or unauthorized access attempts.
- Compliance — many regulatory frameworks require network traffic logging; Flow Logs satisfy this requirement.
Flow Logs don’t capture packet contents (no payload data, nothing privacy-sensitive about message content) — only metadata about the connection itself.
Putting It All Together: A Production VPC Architecture
Let’s walk through a complete, production-grade VPC design — tying together everything from this series.
VPC: 10.0.0.0/16 (us-east-1)
┌─────────────────────────── AZ: us-east-1a ───────────────────────────┐
│ │
│ Public Subnet (10.0.0.0/24) │
│ - Application Load Balancer │
│ - NAT Gateway │
│ - Bastion Host (or replaced by SSM Session Manager) │
│ │
│ Private App Subnet (10.0.10.0/24) │
│ - EC2 Auto Scaling Group instances │
│ - Lambda functions (VPC-attached) │
│ │
│ Private Data Subnet (10.0.20.0/24) │
│ - RDS Multi-AZ primary │
│ - ElastiCache nodes │
│ │
└────────────────────────────────────────────────────────────────────┘
┌─────────────────────────── AZ: us-east-1b ───────────────────────────┐
│ │
│ Public Subnet (10.0.1.0/24) │
│ - Application Load Balancer (second AZ) │
│ - NAT Gateway (second AZ, independent) │
│ │
│ Private App Subnet (10.0.11.0/24) │
│ - EC2 Auto Scaling Group instances │
│ │
│ Private Data Subnet (10.0.21.0/24) │
│ - RDS Multi-AZ standby │
│ - ElastiCache replica │
│ │
└────────────────────────────────────────────────────────────────────┘
VPC Endpoints: S3 (Gateway), DynamoDB (Gateway), Secrets Manager (Interface)
Internet Gateway: attached, referenced only by public subnet route tables
Flow Logs: enabled at VPC level, sent to CloudWatch Logs
Security Groups: alb-sg → app-sg → data-sg (each tier only accepts traffic from the tier above it)
This design embodies every principle covered across the series:
- Multi-AZ everywhere — every tier exists in at least two AZs, enabling the Multi-AZ RDS failover and Auto Scaling resilience from earlier posts
- Tiered network isolation — public subnet for internet-facing load balancers only; private subnets for application logic; the most restricted private subnet for data
- Security groups chained by tier — the database security group only accepts traffic from the app security group, which only accepts traffic from the ALB security group. No tier is directly reachable except through the one above it.
- NAT Gateway per AZ — avoiding cross-AZ dependency and the associated data transfer costs
- VPC Endpoints — S3 and DynamoDB traffic from the private subnets never leaves AWS’s network, and never touches the NAT Gateway
- No public IPs in private subnets — application servers and databases are unreachable directly from the internet, full stop
Real-World Use Cases
Use Case 1: Standard Three-Tier Web Application
The architecture diagrammed above — ALB in public subnets, app servers and Lambda in private app subnets, RDS in private data subnets. This is the default-correct architecture for the vast majority of web applications, and it’s what every EC2, RDS, and Lambda deployment in this series has implicitly assumed.
Use Case 2: Multi-Account, Multi-VPC Enterprise
A large organization with separate AWS accounts per team (best practice for billing isolation and blast-radius containment):
- Each team has its own VPC in its own account
- All VPCs attach to a central Transit Gateway in a shared networking account
- Transit Gateway route tables segment traffic: production VPCs can reach the shared database VPC; development VPCs cannot
- Direct Connect from the Transit Gateway to on-premises for hybrid connectivity
- Centralized Flow Logs aggregated to a security account for monitoring
Use Case 3: Strict Compliance Environment (No Internet Egress)
A healthcare company processing PHI with a no-internet-access requirement for its data processing tier:
- Private subnets with no NAT Gateway at all — genuinely no path to the internet
- All required AWS service access (S3, DynamoDB, Secrets Manager, KMS, CloudWatch) provided via VPC Endpoints exclusively
- NACLs configured with explicit deny rules as defense-in-depth alongside security groups
- VPC Flow Logs feed into a SIEM for continuous compliance monitoring
Use Case 4: Global Low-Latency Application
A gaming company with players worldwide:
- Separate VPCs per region (us-east-1, eu-west-1, ap-southeast-1)
- Each region’s VPC follows the same tiered architecture independently
- Route 53 latency-based routing directs players to their nearest region
- Cross-region VPC Peering connects regions only where needed (e.g., a central analytics VPC pulling data from each regional VPC)
Key Concepts to Carry Forward
A VPC is just an address space until you add subnets, route tables, and gateways. Each component has one job; together they define your entire network topology.
Public vs. private is determined by the route table, not a label. A subnet is public only because its route table sends 0.0.0.0/0 to an Internet Gateway.
NAT Gateway gives private resources outbound internet access without inbound exposure. Deploy one per AZ for true high availability.
Security Groups and NACLs are different tools at different layers. Security groups (stateful, instance-level, allow-only) handle most day-to-day access control. NACLs (stateless, subnet-level, allow/deny) serve as a coarser secondary layer.
VPC Endpoints keep AWS-to-AWS traffic off the public internet. Gateway Endpoints (free, S3/DynamoDB) and Interface Endpoints (PrivateLink, everything else) reduce both cost and exposure.
Transit Gateway scales beyond what VPC Peering can handle. Peering is fine for a few VPCs; Transit Gateway is the right architecture for a real organization with many VPCs and hybrid connectivity.
Flow Logs are your network’s black box recorder. When something doesn’t connect the way you expect, Flow Logs tell you whether traffic was rejected, and by what.
Closing Out the Series
Over five posts, you’ve gone from “what is AWS” to understanding how a real production system fits together:
- IAM controls who can do what across your entire AWS account
- EC2 gives you compute — virtual servers, scaled and priced flexibly
- S3 gives you durable, infinitely scalable object storage
- RDS gives you managed relational databases with automated backups and failover
- Lambda gives you event-driven compute without managing any servers
- VPC — this post — is the network fabric that ties every one of those services together, securely
If you’ve followed the whole series, you now have the conceptual foundation to read AWS’s documentation with real understanding, to make informed architecture decisions, and most importantly, to know why the recommended patterns (private subnets for databases, least-privilege IAM roles, Multi-AZ for production) are recommended — not just that they are.
That’s the actual goal of “beginner” content done right: not memorizing service names, but building a mental model solid enough that the next unfamiliar AWS service is easy to slot into what you already understand.
Thanks for reading the whole series — IAM, EC2, S3, RDS, Lambda, and VPC. If you found it useful, share it with someone starting their AWS journey.
메타데이터
- post_id
- 75c6523c8b92
- slug
- aws-vpc-explained-the-complete-beginners-guide-to-cloud-networking-75c6523c8b92
- url
- https://medium.com/@mammiennor/aws-vpc-explained-the-complete-beginners-guide-to-cloud-networking-75c6523c8b92
- canonical_url
- https://medium.com/@mammiennor/aws-vpc-explained-the-complete-beginners-guide-to-cloud-networking-75c6523c8b92
- author_url
- https://medium.com/@mammiennor
- status
- ok
- fetched_at
- 2026-06-24 23:31:39