Public vs Private Subnet in AWS: What Is the Difference?
In AWS, a public subnet is a subnet whose route table has a route 0.0.0.0/0 → internet gateway (igw-…); instances there with a public IP can be reached from the internet. A private subnet has no route to an internet gateway; for outbound internet (updates) its route table sends 0.0.0.0/0 → NAT gateway. The name you type does not matter — only the route table decides.
Come on, friends! In a society some wings face the main road – shops, visitors come there. Some wings are inside – outsiders don't reach them directly. In AWS these are public and private subnets. But note: the name doesn't decide whether a wing is public or private; the direction written on the notice board – that is, the route table – decides.
चला मित्रांनो! Society मध्ये काही wings main road ला लागून असतात – दुकानं, visitors येतात. काही wings आत असतात – तिथे बाहेरची माणसं थेट येत नाहीत. AWS मध्ये हेच public आणि private subnet. पण लक्ष द्या: wing public आहे की private हे नाव ठरवत नाही, notice board वर लिहिलेली दिशा – म्हणजे route table – ठरवते.
चलो दोस्तों! Society में कुछ wings main road से लगी होती हैं – दुकानें, visitors आते हैं. कुछ wings अंदर होती हैं – वहाँ बाहर के लोग सीधे नहीं आते. AWS में यही public और private subnet हैं. पर ध्यान दो: wing public है या private यह नाम तय नहीं करता, notice board पर लिखी दिशा – यानी route table – तय करती है.
Quick answer
public-rt (associated with web-public-1a) private-rt (associated with app-private-1a)
Destination Target Destination Target
10.0.0.0/16 local 10.0.0.0/16 local
0.0.0.0/0 igw-0abc… (internet gateway) 0.0.0.0/0 nat-0def… (NAT gateway, optional)
Check which route table a subnet really uses with the AWS CLI:
aws ec2 describe-route-tables --filters Name=association.subnet-id,Values=subnet-0123456789abcdef0 \
--query "RouteTables[].Routes[].[DestinationCidrBlock,GatewayId,NatGatewayId]" --output table
Empty result? The subnet has no explicit association and uses the VPC's main route table.
What do I need to understand first?
- A VPC with at least two subnets and an internet gateway attached. If you do not have one yet: How to create a custom VPC in AWS.
- Every subnet is associated with exactly one route table (explicitly, or implicitly with the main route table). One route table can serve many subnets.
- Every route table has the
localroute for the VPC CIDR, so all subnets of a VPC can talk to each other (security groups and network ACLs still apply).
How is traffic routed from a public and a private subnet?
The web server follows public-rt: 0.0.0.0/0 goes to the internet gateway. The app server follows private-rt: 0.0.0.0/0 goes to the NAT gateway in the public subnet. Both tables keep the local route for traffic inside the VPC.
Web server public-rt पाळतो: 0.0.0.0/0 internet gateway कडे जातो. App server private-rt पाळतो: 0.0.0.0/0 public subnet मधल्या NAT gateway कडे जातो. दोन्ही route tables मध्ये VPC च्या आतल्या traffic साठी local route असतो.
Web server public-rt मानता है: 0.0.0.0/0 internet gateway की ओर जाता है. App server private-rt मानता है: 0.0.0.0/0 public subnet के NAT gateway की ओर जाता है. दोनों route tables में VPC के अंदर के traffic के लिए local route रहता है.
| Public subnet | Private subnet | |
|---|---|---|
Route for 0.0.0.0/0 |
Internet gateway (igw-…) |
NAT gateway (nat-…) or none |
| Reachable from the internet | Yes, if the instance has a public IP and the security group allows it | No |
| Can start connections to the internet | Yes (needs a public IP) | Only through a NAT gateway |
| Typical servers | Load balancer, Nginx web server, bastion host, NAT gateway | App servers, databases, internal services |
How do I make a subnet public or private?
Step 1 — Make a subnet public
- VPC → Route tables → select
public-rt→ Routes → Edit routes → Add route →0.0.0.0/0→ Internet Gateway → your IGW → Save. - Subnet associations → Edit subnet associations → tick the subnet → Save.
- Subnets → select the subnet → Actions → Edit subnet settings → Enable auto-assign public IPv4 address (otherwise instances get no public IP and are still unreachable).
Step 2 — Make a subnet private
- Create
private-rt(it starts with only thelocalroute) and associate the private subnets with it. - Do not enable auto-assign public IPv4 there.
- For outbound updates, add
0.0.0.0/0→ NAT Gateway later: NAT gateway for a private subnet.
Step 3 — Verify
- Open the subnet → Route table tab: you should see the
0.0.0.0/0target you expect. - From a public instance:
curl -s https://checkip.amazonaws.comprints the instance's public IP. - From a private instance (through a bastion): the same command prints the NAT gateway's Elastic IP, or times out if there is no NAT. 🔀
Ravindra Bagale's Tip
Naming a subnet public-subnet doesn't make it public! In class I always ask: "Is there an IGW in the route table?" If not, it is private, however nice the name. The reverse is dangerous too: if you add an IGW route to a private subnet's route table by mistake, the database has moved close to the internet. Always check the Route table tab.
Ravindra Bagale's Tip – मराठी
Subnet ला public-subnet नाव दिलं म्हणून तो public होत नाही! मी class मध्ये नेहमी विचारतो: "Route table मध्ये IGW आहे का?" नाही तर तो private आहे, कितीही छान नाव द्या. उलटा पण धोका: private subnet च्या route table मध्ये चुकून IGW route टाकलात तर database internet च्या जवळ पोहोचला. नेहमी Route table tab बघा.
Ravindra Bagale's Tip – हिंदी
Subnet को public-subnet नाम देने से वह public नहीं हो जाता! मैं class में हमेशा पूछता हूँ: "Route table में IGW है क्या?" नहीं है तो वह private है, नाम कितना भी अच्छा दो. उल्टा भी खतरा है: private subnet के route table में गलती से IGW route डाल दिया तो database internet के पास पहुँच गया. हमेशा Route table tab देखो.
How do I fix public/private subnet problems?
Ghabru naka 😅 — these are the usual ones:
| Symptom | Likely cause | Fix |
|---|---|---|
| Instance in "public" subnet times out | No 0.0.0.0/0 → igw-… route, or subnet associated with the main table |
Add the route; associate the subnet with public-rt |
| Public subnet, but no public IP on the instance | Auto-assign public IPv4 disabled | Enable it, or associate an Elastic IP |
Private instance: yum hangs, Curl error (28): Timeout was reached |
No NAT route, or NAT gateway not Available | Add 0.0.0.0/0 → nat-… in private-rt |
| Route shows Blackhole | The NAT gateway or IGW it pointed to was deleted | Edit the route to a working target or remove it |
| New subnets are unexpectedly public | The main route table has an IGW route | Keep the main table private; use a separate public-rt |
Try it at home
Launch one instance in each subnet. From the public one run curl -s https://checkip.amazonaws.com. Then move the private subnet's association to public-rt for two minutes and see what changes — and move it back. Explain the difference in one sentence to a friend.
Learn it properly
Got it? A public subnet means 0.0.0.0/0 → IGW in the route table. A private subnet means no IGW, and a NAT gateway if needed. Don't look at the name, look at the route table.
समजलं का? Public subnet म्हणजे route table मध्ये 0.0.0.0/0 → IGW. Private subnet म्हणजे IGW नाही, गरज असेल तर NAT gateway. नाव नाही, route table बघा.
समझ आया? Public subnet यानी route table में 0.0.0.0/0 → IGW. Private subnet यानी IGW नहीं, ज़रूरत हो तो NAT gateway. नाम नहीं, route table देखो.
Frequently asked questions
What makes a subnet public in AWS?
Its route table has a route 0.0.0.0/0 to an internet gateway. Instances also need a public IP (auto-assign or Elastic IP) to be reachable from the internet.
What is a private subnet?
A subnet whose route table has no route to an internet gateway. Instances there cannot be reached from the internet; for outbound access they use a NAT gateway.
Does the subnet name decide if it is public?
No. The name is only a tag. AWS decides by the route table associated with the subnet.
Can a private subnet access the internet?
Only outbound, through a NAT gateway in a public subnet: the private route table sends 0.0.0.0/0 to the NAT gateway. Inbound connections from the internet remain impossible.
What is the main route table?
The route table every VPC gets automatically. Subnets without an explicit association use it, so keep it private and create a separate public route table.
What does the local route do?
The local route (the VPC CIDR) is in every route table and lets all subnets of the VPC talk to each other. It cannot be removed.