Two subnets use the same CIDR size.
10.64.0.0/24
10.64.1.0/24
Both contain 256 IPv4 address positions.
Both sit inside the same VPC.
Both use security groups.
Both may contain EC2 network interfaces.
The first subnet uses this route table:
Destination Target
10.64.0.0/16 local
0.0.0.0/0 igw-0123456789abcdef0
The second uses:
Destination Target
10.64.0.0/16 local
0.0.0.0/0 nat-0123456789abcdef0
The first subnet is public.
The second is private.
The distinction was not created by:
- the CIDR
- the resource type
- the subnet name
- a security-group rule
- the presence of a database
- the sensitivity of the workload
It was created by the next hop used for internet-bound traffic.
AWS defines a public subnet as one with a direct route to an internet gateway. A private subnet has no direct route to an internet gateway. AWS also distinguishes VPN-only and isolated subnets through their routing behaviour.
Public and private are routing descriptions. They are not security classifications.
That wording sounds almost pedantic.
It prevents a surprising number of architecture mistakes.
A subnet does not contain a privacy switch
An Amazon VPC subnet has:
- an IPv4 and possibly IPv6 CIDR
- one Availability Zone
- an associated route table
- an associated network ACL
- address-assignment attributes
- resources using addresses inside it
The subnet’s type is determined by how its traffic is routed. AWS lists public, private, VPN-only and isolated as routing-derived subnet types.
There is no permanent internal property that says:
privacy = true
and then protects every future resource regardless of later route changes.
A subnet called:
bfstore-prod-private-a
becomes public from a routing perspective if its effective route table gains:
0.0.0.0/0 → internet gateway
A subnet called:
bfstore-prod-public-a
is not public if its effective route table contains only:
10.64.0.0/16 → local
Names document intent.
Route associations create behaviour.
SUBNET NAME
what the architecture intended
│
▼
ROUTE TABLE ASSOCIATION
which table actually applies
│
▼
ROUTES
where traffic actually goes
Reviewing a subnet therefore requires examining its effective route table rather than trusting a tag written several months ago.
Public means a direct internet-gateway route
For IPv4, the characteristic public-subnet route is:
0.0.0.0/0 → igw-id
The destination 0.0.0.0/0 matches every IPv4 address for which no more-specific route exists.
The internet gateway is the direct target.
A minimal public route table might be:
Destination Target
10.64.0.0/16 local
0.0.0.0/0 igw-0123456789abcdef0
The local route handles destinations inside the VPC.
The default route sends other IPv4 destinations to the internet gateway.
RESOURCE
│
▼
SUBNET ROUTE TABLE
│
├── VPC destination → local
│
└── other IPv4 → internet gateway
This classifies the subnet’s path.
It does not prove that every resource inside it can communicate over the public internet or accept internet-initiated traffic.
Those are separate questions.
Routing does not equal exposure
A direct route to an internet gateway is one part of internet connectivity.
For an EC2 instance to initiate IPv4 communication through that gateway, the path normally requires:
DIRECT IPV4 INTERNET EGRESS
internet gateway attached
│
▼
subnet route points to gateway
│
▼
resource has public IPv4 addressing
│
▼
outbound security controls permit traffic
The resource does not need a local listening service merely to initiate an outbound HTTPS request. The remote destination needs to listen.
Internet-initiated inbound reachability has a different chain:
INTERNET-INITIATED INBOUND REACHABILITY
public IPv4 identity
│
▼
direct internet-gateway route
│
▼
inbound security controls permit traffic
│
▼
application is listening
A public subnet supplies the direct route.
It does not grant public exposure by declaration.
Suppose an EC2 instance is placed in a public subnet and has only:
10.64.0.20
as a private IPv4 address.
It has no public IPv4 address and no Elastic IP.
The route table sends public destinations towards the internet gateway, but the instance has no public IPv4 identity through which to communicate directly over the IPv4 internet.
The instance might instead have a public address but a security group allowing inbound traffic only from:
198.51.100.24/32
on:
tcp/443
It is in a public subnet.
It is not open to every source on every port.
PUBLIC SUBNET
│
▼
DIRECT INTERNET ROUTE
does not automatically mean
PUBLICLY REACHABLE RESOURCE
Security groups operate at the resource level.
Network ACLs operate at the subnet level.
Route tables select network paths.
The application decides whether a listening service accepts the connection.
ROUTE
Can the packet reach
the relevant boundary?
SECURITY CONTROL
May the packet cross
that boundary?
APPLICATION
Will the destination
accept it?
The same distinction applies to trust.
A carefully controlled internet-facing load balancer belongs in public subnets because its role requires public routing. Requests arriving through it remain untrusted until DDoS controls, web application firewall rules, TLS, authentication, authorisation and application policy evaluate them.
Traffic from a private subnet is not automatically trustworthy either.
The route explains how a request arrived. Identity, policy and application context decide what it may do.
Public IPv4 auto-assignment is a different subnet setting
A subnet has an attribute controlling whether EC2 instances launched into it request a public IPv4 address for their primary network interface.
That attribute is independent of the subnet’s routing classification. It does not automatically assign public IPv4 addresses to arbitrary secondary network interfaces.
This creates four useful combinations.
| Direct internet-gateway route | Auto-assign public IPv4 | Result |
|---|---|---|
| Yes | Yes | Eligible EC2 instances commonly receive a public IPv4 address on their primary interface and have a direct route |
| Yes | No | Public subnet, but resources need explicit public addressing for direct IPv4 internet access |
| No | Yes | An instance may receive a public address, but the subnet has no direct route to the internet gateway |
| No | No | No direct route and no automatic public IPv4 assignment |
The third combination is particularly educational.
PUBLIC IPv4 ADDRESS
+
NO ROUTE TO INTERNET GATEWAY
=
NO DIRECT INTERNET PATH
The public address does not drag a route table behind it.
Similarly:
INTERNET-GATEWAY ROUTE
+
NO PUBLIC IPv4 ADDRESS
=
NO DIRECT PUBLIC IPv4 IDENTITY
Addressing and routing must agree.
For private subnet classes, I would disable automatic public IPv4 assignment even though routing remains the primary classification. The setting reinforces intent and reduces confusion during troubleshooting.
Defence in depth is often several small controls agreeing politely.
Private is not the same as isolated
A private subnet has no direct route to an internet gateway.
That does not mean it has no path beyond the VPC.
Consider these route tables.
Private with NAT egress
Destination Target
10.64.0.0/16 local
0.0.0.0/0 nat-0123456789abcdef0
Private with central network routing
Destination Target
10.64.0.0/16 local
10.0.0.0/8 tgw-0123456789abcdef0
0.0.0.0/0 tgw-0123456789abcdef0
Private with partner connectivity
Destination Target
10.64.0.0/16 local
172.20.0.0/16 pcx-0123456789abcdef0
Isolated
Destination Target
10.64.0.0/16 local
The first three have no direct route to an internet gateway.
They are private.
They are not isolated.
They can reach destinations outside the VPC through NAT, Transit Gateway, peering, VPN or another routed target.
An isolated subnet has no route to a destination outside the VPC. It may still reach an interface endpoint through the VPC’s local route because the endpoint is represented by private network interfaces inside the VPC.
Gateway endpoints are different. They add explicit service-prefix-list routes for services such as Amazon S3 or DynamoDB and should be evaluated as their own form of private service reachability.
Calling every non-public subnet private hides important differences in network reach.
A more precise subnet vocabulary
Suppose bfstore, the fictional organisation used throughout this series, wants subnet names that describe routing intent rather than imply a security verdict.
A useful vocabulary is:
| Subnet class | Direct IGW route | Other egress | Typical use |
|---|---|---|---|
public-entry |
Yes | Direct internet | Internet-facing load balancer |
public-egress-zonal |
Yes | Direct internet | Zonal public NAT gateway |
private-application |
No | NAT or central egress | EKS nodes and Pods |
private-platform |
No | Endpoints and selected egress | Controllers and platform agents |
private-transit |
No | Transit Gateway | Network attachments |
isolated-data |
No | VPC-local and approved private-service paths | RDS and data-tier resources |
isolated-control |
No | Narrow internal management paths | Sensitive control components |
A Regional NAT Gateway does not require a public-egress-zonal subnet, so that class exists only when the zonal NAT architecture is selected.
The exact route tables decide whether each name remains truthful.
subnet_class: private-application
routes:
- destination: 10.64.0.0/16
target: local
- destination: 0.0.0.0/0
target: transit-gateway
- destination: s3-prefix-list
target: s3-gateway-endpoint
controls:
auto_assign_public_ipv4: false
The name communicates intent.
The route definition proves it.
Private egress has several valid architectures
A private subnet can initiate external communication without becoming public.
The relevant question is not:
Does this subnet use the internet?
It is:
Which next hop provides the path?
Zonal public NAT gateway
The familiar IPv4 pattern sends a private subnet’s default route to a public NAT gateway:
PRIVATE APPLICATION SUBNET
│
▼
0.0.0.0/0 → zonal NAT gateway
│
▼
PUBLIC EGRESS SUBNET
│
▼
0.0.0.0/0 → internet gateway
│
▼
INTERNET
A zonal public NAT gateway:
- is created in a public subnet
- uses Elastic IP addressing for public internet access
- requires the NAT subnet to route towards the internet gateway
- should normally be paired with same-Availability-Zone private routing when used across several zones
For resilient zonal NAT architecture:
AZ A PRIVATE → AZ A NAT → internet gateway
AZ B PRIVATE → AZ B NAT → internet gateway
AZ C PRIVATE → AZ C NAT → internet gateway
The private subnet remains private because its route points to the NAT gateway, not directly to the internet gateway.
Regional NAT Gateway
AWS also provides Regional NAT Gateway availability mode.
A Regional NAT Gateway:
- is a VPC-level resource
- has its own route table
- does not need a public subnet to host it
- uses one NAT gateway ID across Availability Zones
- automatically expands and contracts with the workload footprint to preserve zonal affinity
Regional mode is intended for public egress. It does not provide private NAT connectivity; private NAT use cases continue to use zonal NAT gateways.
Conceptually:
PRIVATE SUBNETS
│
▼
0.0.0.0/0 → Regional NAT Gateway
│
▼
REGIONAL NAT ROUTING
│
▼
INTERNET GATEWAY
│
▼
INTERNET
This model changes the old statement that every public NAT architecture needs a dedicated public subnet in each Availability Zone.
The correct statement is narrower:
A zonal public NAT gateway needs a public subnet. A Regional NAT Gateway does not.
Centralised egress
In a multi-account design, workload VPCs may send default traffic to a Transit Gateway or other central network path:
WORKLOAD PRIVATE SUBNET
│
▼
TRANSIT GATEWAY
│
▼
CENTRAL INSPECTION
│
▼
CENTRAL NAT
│
▼
INTERNET GATEWAY
The workload subnet remains private because it has no direct route to an internet gateway.
The path is longer and requires deliberate design across:
- workload route tables
- Transit Gateway attachment associations
- Transit Gateway route tables
- inspection routing
- egress VPC routes
- return paths
- Availability Zones
- cost
- failure isolation
The word private explains almost none of that.
The path diagram does.
NAT changes source addressing, not the subnet classification
With a zonal public NAT gateway, a private workload sends traffic using its private IPv4 address.
The NAT gateway translates that source to the NAT gateway’s private address. The internet gateway then maps the public NAT gateway’s private address to its Elastic IP for internet communication.
10.64.20.34
private workload
│
▼
10.64.0.10
NAT private address
│
▼
203.0.113.20
NAT Elastic IP
│
▼
internet destination
Responses follow the translation state back to the workload.
The workload itself has not acquired a public IPv4 address.
External systems see the NAT egress address.
This makes NAT useful for:
- outbound IPv4 connectivity
- stable allow-listed egress identities
- sharing public IPv4 addresses
It does not make NAT a firewall replacement.
Security groups, network ACLs, application authentication and destination controls remain relevant.
NAT is an address and connection-path mechanism.
It is not a certificate of privacy.
Private access does not require general internet egress
A workload in a private or isolated subnet may need to access:
- Amazon S3
- AWS APIs
- another VPC
- an internal platform service
- a database
- a private observability endpoint
None of those requirements automatically means:
send traffic through NAT
Interface VPC endpoints create private network interfaces in selected subnets. Workloads reach them using private VPC routing and DNS.
Gateway endpoints for Amazon S3 and DynamoDB add service-specific prefix-list routes to selected route tables.
For example:
Destination Target
10.64.0.0/16 local
pl-s3-prefix-list vpce-s3
The application can reach S3 without a general default route through NAT.
PRIVATE WORKLOAD
│
▼
VPC ENDPOINT
│
▼
AWS SERVICE
EKS clusters with limited or no internet access similarly need an explicit dependency plan for the AWS APIs, registries, package sources and telemetry destinations they use.
Private does not mean disconnected.
It means the paths are deliberate.
A private subnet can have a large blast radius
Imagine a subnet with no internet-gateway route.
It is labelled private.
Its route table contains:
10.0.0.0/8 → transit gateway
The transit gateway connects:
- production
- staging
- shared services
- observability
- backup
- corporate networks
- partner networks
The subnet has no direct internet path.
It can still reach a substantial part of the organisation.
NO DIRECT INTERNET ROUTE
does not mean
SMALL NETWORK REACH
A broad private route can carry more organisational consequence than one carefully controlled public endpoint.
This is why subnet documentation should describe actual reachability:
subnet:
class: private-application
direct_internet_gateway_route: false
reachable_networks:
- shared-services
- observability
- backup
internet_egress:
path: central-egress
inspection: required
inbound:
sources:
- public-alb-security-group
The word private remains useful shorthand.
The full contract explains what the subnet can actually reach.
Public and private IPv6 require two decisions
IPv6 often uses globally unique addresses without IPv4-style public-address translation.
Subnet classification still depends on routing.
For AWS public IPv6 space:
Direct public IPv6 route
::/0 → internet gateway
This creates a direct IPv6 path to the internet gateway.
Outbound-only IPv6 route
::/0 → egress-only internet gateway
An egress-only internet gateway allows resources to initiate outbound IPv6 communication while preventing internet hosts from initiating connections through that gateway.
PRIVATE DUAL-STACK SUBNET
IPv4:
0.0.0.0/0 → NAT or central egress
IPv6:
::/0 → egress-only internet gateway
This example assumes that the subnet uses public global-unicast IPv6 space.
AWS also supports private IPv6 space. AWS does not advertise that space publicly and drops it at the internet-gateway edge even when the VPC contains an internet gateway or egress-only internet gateway and a route points towards it.
The complete model is therefore:
ADDRESS TYPE
+
ROUTE
+
SECURITY POLICY
=
ACTUAL REACHABILITY
AWS treats IPv4 and IPv6 routes independently.
Adding:
0.0.0.0/0
does not create:
::/0
Dual-stack architecture requires two deliberate path decisions.
The main route table can change subnet behaviour quietly
Every subnet must use one route table.
A subnet may be explicitly associated with a custom table or implicitly associated with the VPC’s main route table. One subnet can use only one subnet route table at a time, while one route table may serve several subnets.
Suppose a new data subnet is created without an explicit association.
It inherits the main route table:
10.64.0.0/16 → local
Later, someone adds:
0.0.0.0/0 → internet gateway
to the main route table.
Every implicitly associated subnet now receives that direct route.
ONE MAIN-TABLE CHANGE
│
▼
MANY SUBNET ROUTING CHANGES
The resource names and diagrams may still say:
private
data
internal
The routing behaviour has changed underneath them.
For important subnet classes, I prefer explicit associations and a deliberately quiet main route table.
public-entry-a
→ public-entry-routes-a
application-a
→ application-routes-a
data-a
→ data-routes-a
transit-a
→ transit-routes-a
A subnet should not inherit a major network path because nobody remembered to mention the route table in the module.
Shared route tables create shared consequences
Several subnets may share one route table.
That is valid.
It also means every route change affects every associated subnet.
Suppose these subnet types share:
bfstore-private-routes
- application nodes
- databases
- internal controllers
- interface endpoints
- observability agents
A new default route to Transit Gateway is added for application egress.
The database subnet receives it too.
SHARED ROUTE TABLE
│
├── application subnet
├── database subnet
├── controller subnet
└── endpoint subnet
The route may be harmless.
It may also broaden paths that were never intended for the data tier.
Subnet grouping should follow common routing requirements, not merely the word private.
Useful route-table classes may include:
private-application-egress
private-platform-egress
private-transit
isolated-data
isolated-control
A little more naming precision prevents a broad route table from becoming a communal coat that unrelated subnet types are forced to wear.
The bfstore edge pattern
For bfstore, the public application path should be narrow.
INTERNET
│
▼
INTERNET GATEWAY
│
▼
PUBLIC ENTRY SUBNETS
│
▼
INTERNET-FACING ALB
│
▼
PRIVATE APPLICATION SUBNETS
│
▼
EKS PODS
The public subnets exist for components that need direct internet routing:
- internet-facing load balancer nodes
- zonal public NAT gateways, when that egress model is selected
- selected edge appliances
They should not become general-purpose workload subnets.
Private application subnets can hold:
- EKS nodes
- application Pods
- internal load-balancer targets
- service network interfaces
Data subnets can hold:
- RDS resources
- data-tier interfaces
- components requiring narrower connectivity
A database is not protected merely because its subnet name contains private.
Its route table, public-accessibility setting, security groups, authentication, encryption and operational access path must all agree with the intended boundary.
A public subnet should not become the automatic landing zone for administration either.
A bastion host with a public address can be made to work, but alternatives may include:
- AWS Systems Manager Session Manager
- private VPN access
- Direct Connect
- identity-aware access tooling
- ephemeral administrative access
Public routing should exist because a component requires public routing, not because the component was inconvenient to reach privately.
Common misunderstandings
“A private subnet has no internet access”
Not necessarily.
It may use a zonal NAT gateway, Regional NAT Gateway, central egress or an egress-only internet gateway.
“A public subnet exposes everything inside it”
No.
Resources also require suitable public addressing, security controls and listening services for internet-initiated reachability.
“A public IP makes a subnet public”
No.
The route table determines the subnet type.
“A security group makes a subnet private”
No.
Security groups filter resource traffic. They do not select the network’s next hop.
“No internet route means isolated”
Not necessarily.
The subnet may still route to Transit Gateway, VPN, peering or other external networks. It may also reach interface endpoints through VPC-local routing.
“Private means trusted”
No.
Private describes the route path, not the identity or integrity of the source.
“Every NAT gateway belongs in a public subnet”
No.
A zonal public NAT gateway does. A Regional NAT Gateway does not require a public subnet.
“The subnet name proves its type”
No.
Inspect the actual route-table association and routes.
Questions I now ask
| Area | Core question |
|---|---|
| Routing | Which route table applies, and where does each address family go? |
| Addressing | Does the resource have public or private IPv4 or IPv6 identity? |
| Exposure | Which listeners and security controls permit inbound traffic? |
| Egress | Does traffic use zonal NAT, Regional NAT, egress-only gateway or central routing? |
| Reach | Which internal and external networks are reachable? |
| Isolation | Are there any routes beyond the VPC, including service-prefix routes? |
| Coupling | Which other subnets share the route table? |
| Return path | Can responses return through the correct routing domains? |
| Ownership | Who may change the route table or association? |
| Evidence | Can the intended classification be verified automatically from the routes? |
These questions turn public and private from reassuring adjectives into testable network statements.
The mental model I am keeping
My earlier model was:
PUBLIC SUBNET
unsafe
PRIVATE SUBNET
safe
The stronger model is:
SUBNET
│
▼
ASSOCIATED ROUTE TABLE
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
DIRECT IGW ROUTE INDIRECT EGRESS VPC-LOCAL ONLY
│ │ │
▼ ▼ ▼
PUBLIC PRIVATE ISOLATED
│ │ │
└──────────────────┼──────────────────┘
▼
ADDRESSING CHOICES
│
▼
SECURITY CONTROLS
│
▼
APPLICATION
│
▼
ACTUAL REACHABILITY
The route table answers:
Where may packets go next?
The direct internet-gateway route answers:
Is this subnet public
from a routing perspective?
NAT, egress-only gateways or central routing answer:
Can a private workload
initiate external communication?
Public addressing answers:
Does this resource possess
an internet-routable identity?
Security groups and network ACLs answer:
Which correctly routed traffic
may cross the relevant boundary?
The listener answers:
Is an application ready
to accept the connection?
Identity and authorisation answer:
What may the connected actor do?
And isolation answers:
Does the subnet have any route
to a destination beyond its VPC?
Public and private are useful terms.
They become dangerous when treated as security conclusions.
A public subnet is not necessarily exposed, and a private subnet is not necessarily isolated.
The public subnet may hold one carefully controlled load balancer and nothing else.
The private subnet may reach dozens of networks through Transit Gateway.
The isolated subnet may contain a database whose security group is still too broad.
The route tells me where the packet can travel.
The address tells me how the endpoint may be reached.
The security controls tell me which traffic may proceed.
The application tells me what happens after arrival.
Privacy is the outcome of all those layers agreeing.
The subnet label merely points towards the first one.
References and further reading
-
Subnets for your VPC Defines public, private, VPN-only and isolated subnet types through routing behaviour.
-
Subnet route tables Covers local routes and explicit or implicit subnet associations.
-
Route table concepts and configuration Defines main and custom route tables, destinations, targets and associations.
-
How route priority works Explains longest-prefix matching and route-selection priority.
-
Enable internet access using an internet gateway Covers internet-gateway routing and public addressing.
-
Modify subnet IP addressing attributes Documents automatic public IPv4 requests for EC2 instances launched into a subnet.
-
NAT gateways Explains public and private NAT gateway modes and unsolicited inbound behaviour.
-
NAT gateway basics Covers zonal NAT gateway resilience and same-zone routing.
-
Regional NAT gateways Describes VPC-level NAT, automatic multi-AZ expansion and the absence of a public-subnet hosting requirement.
-
NAT gateway use cases Provides routing and source-address translation examples.
-
Egress-only internet gateways Explains outbound-only IPv6 internet connectivity.
-
IP addressing for VPCs and subnets Documents public and private IPv6 behaviour, including gateway-edge handling of private IPv6 space.
-
AWS PrivateLink and VPC endpoints Covers private connectivity through interface and gateway endpoint models.
-
Gateway endpoints Explains service-prefix routes for Amazon S3 and DynamoDB.
-
Amazon VPC security Describes the separate roles of security groups, network ACLs, flow logs and routing.
-
Amazon EKS subnet best practices Describes public ingress and private worker-subnet patterns.