AWS VPC

Amazon Virtual Private Cloud (VPC) is your own isolated virtual network inside AWS — the foundation every other AWS resource runs in. An EC2 instance, an RDS database, an EKS cluster: all live inside a VPC, and the VPC's subnets, routing, and firewall rules determine what can talk to what and what's reachable from the internet. Understanding VPC is understanding how AWS connectivity and network security actually work.

The core idea mirrors traditional data-center networking (cloud networking concepts apply directly): you carve an IP address range into subnets, decide which are public (internet-reachable) and which are private (internal-only), wire them together with route tables and gateways, and control traffic with security groups. Getting the public/private split right is the difference between a database safely hidden from the internet and one accidentally exposed to the world.

TL;DR

Core Concepts

Subnets and Availability Zones

A VPC spans a region; subnets are slices of its IP range, each pinned to one availability zone. For resilience you spread resources across multiple AZs (a subnet per AZ), so one AZ failure doesn't take you down. The critical property is public vs private:

Routing and Gateways

Route tables attached to subnets decide where traffic goes based on destination:

The NAT gateway is the key to the private-subnet pattern: your database can download patches and call AWS APIs (outbound) while remaining completely unreachable from the internet (no inbound).

Security Groups vs NACLs

Two firewall layers, often confused:

Security groups are your primary tool — stateful (allow a request in, its response goes out automatically), attached to instances, and the everyday way you say "the load balancer can reach the app on 443; the app can reach the DB on 5432." NACLs are a coarser subnet-wide backstop, useful for broad denies (block an IP range) but not your main control. A key pattern: security groups can reference other security groups as sources ("allow the app-sg to reach the db-sg"), which is cleaner than hardcoding IPs.

A Secure Baseline Architecture

The pattern that keeps databases off the internet:

The load balancer is the only internet-facing resource; everything else lives in private subnets, reachable only from the specific security groups that need it. This is defense in depth at the network layer — and the zero-trust instinct of "nothing is reachable unless explicitly permitted."

Common Mistakes

Databases in Public Subnets

The classic breach: an RDS instance or database in a public subnet with a security group open to 0.0.0.0/0, discoverable by internet scanners. Databases belong in private subnets with security groups allowing access only from your app's security group. If it's on the internet, it will be found.

Overly Open Security Groups

0.0.0.0/0 on port 22 (SSH), 3389 (RDP), or database ports exposes those services to the entire internet — constant brute-force target. Restrict sources to specific IPs, security groups, or use Systems Manager Session Manager for SSH-free access. Open only the ports you need, from the narrowest sources.

Confusing Security Groups and NACLs

Treating NACLs as the primary firewall (they're stateless, so you must remember return-traffic rules) or forgetting security groups are stateful. Use security groups as the main control; reserve NACLs for coarse subnet-level denies.

No NAT Gateway (or One Per AZ Missing)

Private instances that can't reach the internet fail to pull updates or call external APIs. You need a NAT gateway (in a public subnet) with private route tables pointing to it — ideally one per AZ for resilience (a single NAT gateway is an AZ-level single point of failure and a cross-AZ data-transfer cost).

Undersized or Overlapping CIDRs

Picking a small CIDR you outgrow, or a range that overlaps with other VPCs/on-prem networks you'll later need to peer with, causes painful re-architecture. Plan the IP space with room to grow and non-overlapping ranges. See cloud networking.

FAQ

What's the difference between a public and private subnet?

Only the routing: a public subnet has a route to an internet gateway (resources can be internet-reachable); a private subnet does not (resources are internet-isolated, reaching out only via a NAT gateway). There's no separate "public/private" setting — it's entirely determined by the route table. Put internet-facing things (load balancers) in public subnets and everything else (apps, databases) in private ones.

Security group or NACL — which do I use?

Security groups for almost everything — they're stateful (return traffic is automatic), instance-level, and can reference other security groups. Use NACLs only as a coarse subnet-wide backstop (e.g., blocking a malicious IP range across a whole subnet). Trying to manage fine-grained access with stateless NACLs is painful and error-prone.

How do private instances access the internet?

Through a NAT gateway in a public subnet, with the private subnet's route table sending internet-bound traffic to it. This allows outbound connections (pulling updates, calling APIs) while keeping the instances unreachable inbound from the internet. For AWS services specifically, VPC endpoints keep that traffic off the internet entirely.

Do I need to design a VPC from scratch?

Not always — AWS provides a default VPC, and tools (Terraform, CDK, the VPC wizard) generate the standard multi-AZ public/private layout. For production, use infrastructure as code to define a VPC with the public/private-subnet-per-AZ pattern rather than clicking it together. Understanding the pieces still matters for security and debugging.

How do I connect a VPC to other networks?

VPC Peering or Transit Gateway to connect VPCs to each other; VPN or Direct Connect to link to on-premises data centers; VPC Endpoints to reach AWS services privately. Transit Gateway is the scalable hub-and-spoke choice when connecting many VPCs and networks.

Related Topics

References