Updated recently
Last updated:
Quick Answer: A VPC is your private network inside AWS. You divide it into subnets (public or private), attach a route table to each subnet that decides where traffic goes, use a NAT gateway to let private-subnet resources reach the internet, and enable VPC Flow Logs to see what actually happened. Security groups are stateful firewalls on instances; NACLs are stateless filters on subnets.
Why VPC Confuses Everyone at First
VPC has a reputation for being the concept that stops cloud beginners, and the reason is that it is the first place where AWS stops managing things for you. Compute and storage are relatively forgiving. Networking is not — a misconfigured route table can quietly break connectivity in ways that look like application bugs.
The other reason it is confusing is that the AWS console presents it as many separate pieces — VPC, subnets, route tables, internet gateways, NAT gateways, security groups, NACLs, endpoints — when really you are building one interconnected system. Once you see how the pieces connect, it becomes straightforward.
The Mental Model
Think of a VPC as a private data centre you have drawn a fence around. Inside that fence you carve out rooms (subnets). Each room has a door policy (route table) saying which exits traffic may use. The public rooms have a door to the outside world (internet gateway). The private rooms do not — they reach the internet through a shared guarded exit (NAT gateway). Guards stand at each room door checking credentials (security groups and NACLs).
Subnets: Public and Private
A subnet is a range of IP addresses inside your VPC. The only thing that makes a subnet public is that its route table has a route to an internet gateway. Nothing else. There is no “public” toggle — it is purely a routing decision.
# Public subnet route table — routes directly to the internet
10.0.0.0/16 -> local (always present)
0.0.0.0/0 -> igw-0abc123 (internet gateway)
# Private subnet route table — internet only via NAT
10.0.0.0/16 -> local
0.0.0.0/0 -> nat-0def456 (NAT gateway)
The standard production pattern is at least two AZs, with public and private subnets in each. Your load balancer goes in a public subnet. Your application servers and databases go in private subnets, where they cannot be reached directly from the internet.
NAT Gateway: The Piece Everyone Gets Wrong
A NAT gateway lets resources in private subnets reach the internet for outbound traffic — pulling package updates, calling external APIs — while preventing inbound internet connections. It is the single most common source of unexpected AWS bills and the most common cause of “why can’t my server download anything.”
The bill trap: a NAT gateway costs money per hour and per GB processed, and it is easy to leave running in a development environment that nobody remembers. In ap-south-1 that is roughly ₹2 an hour plus data processing. Not catastrophic for one, quietly expensive across a forgotten estate of a dozen.
The connectivity trap: if your private subnet cannot reach the internet, check the route table has 0.0.0.0/0 -> nat-xxxx and that the NAT gateway is in the same AZ as the subnet using it. Cross-AZ NAT does not work and produces errors that look nothing like a routing problem.
A cheaper alternative worth knowing for many workloads: VPC endpoints. If your private instances only need to reach S3 or DynamoDB, a gateway endpoint gives them access with no NAT gateway and no internet route — often a large cost saving.
Security Groups vs NACLs
This distinction is asked in almost every cloud interview, and getting it wrong is a red flag.
| Aspect | Security Group | Network ACL |
|---|---|---|
| Applies to | Instances (ENIs) | Subnets |
| Stateful? | Yes — return traffic auto-allowed | No — you must allow both directions |
| Rules | Allow only | Allow and deny |
| Evaluation | All rules evaluated | Rules evaluated in order by number |
| Use for | Primary firewall, per-instance | Broad subnet-level blocking |
The statefulness point is the one that catches people. Because a security group is stateful, you only need to allow inbound SSH from your IP; the response traffic flows back automatically. A NACL is stateless, so if you allow inbound SSH you must also add an outbound rule for the ephemeral port range, or the response never gets back.
VPC Flow Logs: How You Actually Debug This
When networking misbehaves and you cannot see why, Flow Logs are how you find out. They record IP traffic metadata — source, destination, port, action — without capturing packet contents.
Two things to check in the logs whenever connectivity fails:
- REJECT entries — the action field tells you definitively whether traffic was blocked, and at which hop the block occurred based on source and destination.
- Missing entries — if traffic never appears at all, the problem is upstream of where you are looking, usually a route table rather than a firewall.
# Enable Flow Logs via CLI, delivered to CloudWatch Logs
aws ec2 create-flow-logs
--resource-type VPC
--resource-ids vpc-0abc123def456
--traffic-type ALL
--log-destination-type cloud-watch-logs
--log-group-name /vpc/flowlogs
--deliver-logs-permission-arn arn:aws:iam::123456789012:role/FlowLogRole
For production, send Flow Logs to S3 and query with Athena rather than CloudWatch — it is far cheaper at volume and you will actually keep it enabled.
A Working Configuration to Build
If you are learning, build this and take the AWS Solutions Architect exam with it genuinely in your head:
- VPC with CIDR
10.0.0.0/16across two AZs - Two public subnets (load balancer) and two private subnets (app servers)
- Internet gateway on the public route table
- NAT gateway in one public subnet, referenced by the private route table
- Security group on the ALB allowing 80/443 from anywhere
- Security group on app instances allowing traffic only from the ALB security group — not from 0.0.0.0/0
- RDS in the private subnets, allowing access only from the app security group
- Flow Logs enabled on the VPC, delivered to S3
That last point — chaining security groups by reference rather than opening CIDR ranges — is the difference between a design an interviewer respects and one they do not.
Training Resources
Networking is the module most often rushed and most often tested. Build it properly with SkilBrill AWS Networking Training. For the broader design context, see AWS Cloud Architecture Training.
FAQ
What is the difference between a public and private subnet in AWS?
Only routing. A public subnet has a route to an internet gateway; a private subnet does not and reaches the internet through a NAT gateway. There is no separate configuration flag.
Why is my private subnet unable to reach the internet?
Almost always one of three things: the route table is missing a 0.0.0.0/0 route to the NAT gateway, the NAT gateway is in a different availability zone than the subnet, or the security group outbound rules block the traffic. Check the route table first.
Security group or NACL — which should I use?
Security groups for almost everything. They are stateful, simpler, and operate at the instance level. NACLs are useful for broad subnet-level deny rules, such as blocking a known malicious IP range.
Do VPC Flow Logs capture packet contents?
No. They record metadata only — source and destination IP, ports, protocol and accept/reject action. Payloads are never captured, which is why they are safe to enable broadly.
How can I reduce NAT gateway costs?
Use VPC gateway endpoints for S3 and DynamoDB instead of routing through NAT, share a single NAT gateway across multiple private subnets in the same AZ where fault tolerance allows, and delete unused NAT gateways in development environments.
