An Amazon VPC is a virtual network you define inside AWS: you choose the IP ranges, split them into subnets, and decide which traffic can leave and where it goes. Everything else in the network is an attachment to that decision.
The mental model that saves the most time:
- a VPC is the network boundary, with an IPv4 CIDR block you choose;
- subnets are ranges carved out of that block, and each one lives in exactly one Availability Zone;
- route tables decide where traffic from a subnet goes, by matching a destination to a target;
- gateways and endpoints are the exits: an internet gateway for public traffic, a NAT device for private subnets that need outbound access, a VPC endpoint to reach AWS services without leaving the AWS network;
- security groups and network ACLs decide what is allowed, at the instance level and the subnet level.
Accounts created after December 4, 2013 already have a default VPC in every Region, with a subnet per Availability Zone, an attached internet gateway, a route to that gateway in the main route table, and DNS settings that give instances public DNS names. That default network is useful for labs and misleading for production, because it is public by default.
VPC and subnets: the objects everything attaches to
A VPC is logically isolated from other virtual networks in AWS. You can pick any IPv4 range you like inside the private address space, add subnets, and attach gateways and security groups to them.
A subnet is a range of IP addresses inside the VPC, and it must reside in a single Availability Zone. That single-AZ constraint is what makes subnet design a resilience decision, not just an addressing decision: a subnet cannot span zones, so multi-AZ availability means multiple subnets.
You can assign both IPv4 and IPv6 addresses, bring your own public IPv4 and IPv6 addresses to AWS, and allocate them to resources such as instances, NAT gateways, and Network Load Balancers.
| Component | Scope | What it decides |
|---|---|---|
| VPC | Region, one or more AZs | The address space and the isolation boundary |
| Subnet | One Availability Zone | Which addresses exist in that zone |
| Route table | VPC, associated to subnets | Where traffic from those subnets is sent |
| Security group | Instance or ENI | Which traffic reaches the resource |
| Network ACL | Subnet | Which traffic enters or leaves the subnet |
Route tables: the traffic controller
A route table is the traffic controller for a VPC. Each table contains routes, and each route pairs a destination (a CIDR block or a prefix list) with a target (an internet gateway, NAT gateway, VPC peering connection, or VPN connection). AWS creates the main route table with the VPC and routes traffic by destination IP address.
The same mechanism produces the four subnet patterns people talk about:
- public subnet – the route table has a route to an internet gateway;
- private subnet – no route to an internet gateway; outbound internet access, if needed, goes through a NAT device;
- VPN-only subnet – routes point to a virtual private gateway for on-premises connectivity;
- isolated subnet – no route to anything outside the VPC.
When more than one route matches a destination, AWS applies the most specific match; the detailed ordering rules live in the Route priority page of the VPC documentation.
Leaving the VPC: internet gateway, NAT, and endpoints
Three different exits solve three different problems:
- an internet gateway connects a VPC to the internet, for subnets whose route table points at it;
- a NAT device gives private subnets outbound internet access without accepting inbound connections from the internet;
- a VPC endpoint connects to AWS services privately, without an internet gateway or NAT device at all. For traffic between your VPC and services like S3 or DynamoDB, this is usually the cheapest and the most secure option, because the traffic never leaves the AWS network.
If a private subnet only talks to AWS services, endpoints remove the NAT gateway from the design, and with it the hourly and per-GB cost of that gateway.
Connecting VPCs and remote networks
- VPC peering routes traffic between two VPCs directly, and it does not require a gateway in the middle. It does not transit: if A peers with B and B peers with C, A cannot reach C through B.
- Transit gateway acts as a central hub for VPCs, VPN connections, and Direct Connect connections, which is the usual answer once peering becomes a mesh you cannot document.
- Site-to-Site VPN connects a VPC to an on-premises network over IPsec tunnels.
Choosing between them is mostly a question of how many networks you are connecting and whether you need transitive routing. Two VPCs, one link: peering. Ten VPCs and an office: transit gateway or VPN with a hub.
Security groups and network ACLs
Both control traffic, at different layers, and the difference explains most “the rule is open but the connection still fails” tickets:
| Security group | Network ACL | |
|---|---|---|
| Attaches to | Instances and network interfaces | Subnets |
| Rules | Allow only | Allow and deny |
| State | Stateful: a reply to allowed inbound traffic is allowed automatically | Stateless: return traffic needs its own rule |
| Rule numbering | Not numbered | Numbered 1 to 32766, evaluated in order |
| Scope | The resource | Everything in the subnet |
Security groups are stateful: if inbound traffic is allowed, the response is allowed regardless of outbound rules. Network ACLs are stateless, so both directions need explicit rules, and they do not filter traffic to and from Amazon DNS.
Short recommendation: start with security groups only, and add network ACLs when you need a subnet-wide deny that an instance-level rule cannot express. Two layers of overlapping rules are hard to debug at 3 a.m.
Default VPC: what you actually get
If your account was created after December 4, 2013, each Region has a default VPC that is configured and ready to use:
- a default subnet in each Availability Zone;
- an attached internet gateway;
- a route in the main route table that sends traffic to that internet gateway;
- DNS settings that assign public DNS hostnames to instances with public IP addresses and enable DNS resolution through the Amazon-provided DNS server.
An EC2 instance launched into a default subnet gets internet access automatically, and if you launch an instance without specifying a subnet, AWS picks a default subnet for you. That is convenient for a first lab and a finding in any review that expects production workloads to sit in private subnets.
Inspecting a VPC with the AWS CLI
The CLI answers most “what does this network actually look like” questions in a few commands. If you have not installed it yet, start with our AWS CLI installation guide for Ubuntu.
# address space and default VPC flag
aws ec2 describe-vpcs --query 'Vpcs[*].[VpcId,CidrBlock,IsDefault]' --output table
# subnets, with the zone each one lives in
aws ec2 describe-subnets --query 'Subnets[*].[SubnetId,AvailabilityZone,CidrBlock,MapPublicIpOnLaunch]' --output tableCode language: Bash (bash)
Route tables are where the “public or private” question is settled:
aws ec2 describe-route-tables \
--query 'RouteTables[*].{Table:RouteTableId,Routes:Routes[*].[DestinationCidrBlock,GatewayId,NatGatewayId,State]}' \
--output jsonCode language: Bash (bash)
Security groups and network ACLs answer the access question:
aws ec2 describe-security-groups --query 'SecurityGroups[*].[GroupId,GroupName,Description]' --output table
aws ec2 describe-network-acls --query 'NetworkAcls[*].[NetworkAclId,VpcId,IsDefault]' --output tableCode language: Bash (bash)
Flow logs give you the traffic evidence when the configuration looks right and the connection still fails:
aws ec2 create-flow-logs \
--resource-type VPC --resource-ids vpc-0123456789abcdef0 \
--traffic-type ALL --log-destination-type cloud-watch-logs \
--log-group-name /aws/vpc/flowlogsCode language: Bash (bash)
Design checklist
| Question | Answer that keeps the design simple |
|---|---|
| How many subnets? | At least one per Availability Zone you intend to survive the loss of |
| Public or private? | Private by default, public only for load balancers and bastion-free access patterns |
| How do private subnets reach the internet? | NAT gateway for general egress, VPC endpoints for AWS services |
| Peering or transit gateway? | Peering for a handful of VPCs, transit gateway once the mesh stops being obvious |
| Where do you enforce deny rules? | Network ACL at the subnet edge, security groups at the resource |
What to do next
The components above only make sense once you connect them to the rest of an AWS account. AWS Services Explained for Developers covers the services that sit inside a VPC and the ones that do not. Essential AWS Features for DevOps Engineers puts networking next to the other operational areas you are expected to own. When you need to link two VPCs, Amazon VPC Peering Explained goes deeper than the summary here, and AWS Site-to-Site VPN: Tunnels, Gateways, and Routing covers the hybrid case. If you also work in Google Cloud, AWS vs GCP Services Comparison maps the networking services by name.
Sources
- What is Amazon VPC? – VPC features, gateways and endpoints, peering, transit gateways, flow logs
- How Amazon VPC works – VPCs and subnets, default and nondefault VPCs, the December 4, 2013 rule
- Configure route tables – main route table, destinations and targets, public/private/VPN-only/isolated subnets
- Control subnet traffic with network access control lists – subnet-level allow and deny rules, rule numbers, stateful security groups versus stateless ACLs
FAQ
These answers cover the VPC decisions that come up most often in reviews: subnet scope, the difference between security groups and network ACLs, endpoints versus NAT, default VPCs, and how to tell a public subnet from a private one.
What is the difference between a security group and a network ACL in Amazon VPC?
A security group attaches to instances and network interfaces and only contains allow rules, and it is stateful, so a response to allowed inbound traffic is allowed automatically. A network ACL attaches to a subnet, contains both allow and deny rules numbered 1 to 32766, and is stateless, so return traffic needs its own rule. Use security groups for day-to-day access control and network ACLs when you need a subnet-wide deny.
Does every AWS account have a default VPC?
Accounts created after December 4, 2013 have a default VPC in each Region, with a default subnet in every Availability Zone, an attached internet gateway, a route to that gateway in the main route table, and DNS settings that assign public DNS hostnames. Instances launched into a default subnet get internet access automatically, which is why production workloads usually belong in a VPC you designed yourself.
When should I use a VPC endpoint instead of a NAT gateway?
Use a VPC endpoint when the private subnet only needs to reach AWS services. Endpoints connect to services privately without an internet gateway or NAT device, so the traffic stays inside the AWS network and you remove the NAT gateway’s hourly and per-GB charges. Keep a NAT gateway for general outbound internet access from private subnets, such as package downloads or third-party APIs.
Can a subnet span multiple Availability Zones?
No. A subnet must reside in a single Availability Zone, which is why multi-AZ resilience is expressed as multiple subnets rather than one larger subnet. When you create a VPC with subnets in two Availability Zones, you get independent failure domains for the resources in each subnet.
How do I check whether a subnet is public or private?
Look at its route table, not at the subnet itself. A subnet is public when its associated route table sends 0.0.0.0/0 to an internet gateway, and private when that route points to a NAT gateway or does not exist. `aws ec2 describe-route-tables` shows the destinations and targets that decide the answer.








Leave a Reply