INSIGHTS
Networking

AWS SAA-C03: Public vs Private Subnets

In this article
  1. Define public and private by routing, not by the name
  2. Use public subnets for internet-facing infrastructure that needs them
  3. Use private subnets for application and data tiers
  4. Repeat subnet tiers across Availability Zones
  5. Separate route tables when egress behavior differs
  6. Use security groups as primary workload firewalls
  7. Prefer private endpoints for supported AWS services
  8. Plan IPv6 separately from IPv4
  9. Validate reachability from the route outward

Public and private subnets are among the first concepts people learn in Amazon VPC, yet the labels are frequently misunderstood. A subnet is public because its route table has a route to an internet gateway, not because every resource inside it is exposed. A private subnet lacks that direct route, but its resources can still reach external destinations through NAT or private service paths.

For SAA-C03, this routing-first definition is the foundation for secure multi-tier design. Public ingress, private application tiers, data subnets, NAT, VPC endpoints, IPv6, security groups, and network ACLs all make more sense once the route table is treated as the source of truth for what each subnet can reach.

Define public and private by routing, not by the name

In Amazon VPC, a subnet is public when its route table has a route to an internet gateway; a subnet without a direct route to an internet gateway is private. The label is therefore a routing property, not a security classification or a checkbox that automatically protects resources. That distinction is foundational for SAA-C03 network architecture.

A resource in a public subnet is not automatically reachable from the internet. It also needs an appropriate public IPv4 or IPv6 address, security-group rules, network ACL behavior, and an application listening on the relevant port. Conversely, a resource in a private subnet can still initiate outbound internet traffic through NAT or reach private services through endpoints.

General subnet segmentation principles help organize address space, but AWS route tables and gateways determine whether the subnet is public or private in practice.

Subnet labels should be derived from architecture intent and verified against the route table during reviews. Teams sometimes call a subnet “private” because instances have no public IPs even though the route table points directly to an internet gateway. That is not a private subnet in AWS terminology, and the naming mismatch can cause security reviews to miss how easily a future resource with a public address could become reachable.

Use public subnets for internet-facing infrastructure that needs them

Internet-facing Application or Network Load Balancers commonly use public subnets so their load-balancer nodes can receive traffic through the internet gateway. Zonal NAT gateways also live in public subnets when providing public NAT. Bastion hosts are less common in modern architectures but, where used, are another example of infrastructure that may deliberately need public reachability.

Do not place application servers in public subnets merely because a load balancer is public. The load balancer can accept internet traffic and forward it to targets in private subnets. This creates a clearer trust boundary and reduces the number of resources with public addresses.

Keep public subnet route tables small and explicit. The default IPv4 route points to the internet gateway, while local VPC routes handle internal traffic. Additional transit, inspection, or peering routes should have clear ownership because overlapping and more-specific routes can change the traffic path.

If an internet-facing ALB spans two public subnets, its targets can still live exclusively in private subnets. The security-group reference from target to ALB is more important than sharing a subnet type. Keeping compute private also simplifies patching and administration because operators are encouraged to use Systems Manager or controlled internal access instead of direct SSH or RDP from the internet.

Use private subnets for application and data tiers

Application servers, container tasks, databases, caches, and internal services usually belong in private subnets when they do not need direct inbound internet access. Private placement does not make them secure by itself, but it removes a direct route to the internet gateway and encourages access through controlled ingress layers.

Private subnets can still reach internal AWS services, other VPCs, on-premises networks, and the internet through designed paths. Route tables may point to NAT, Transit Gateway, virtual private gateways, VPC endpoints, or inspection appliances. The important property is that internet reachability is not direct.

Subnet sizing deserves planning because each subnet exists entirely in one Availability Zone. The guidance in choosing subnet sizes is relevant: leave enough address space for scaling, load-balancer interfaces, container tasks, managed services, and future growth.

Data tiers often deserve even tighter routing than application tiers. A database subnet may have no default route to NAT because the database should not initiate arbitrary internet connections. Patch and management traffic for managed database services is handled by the service itself, while self-managed database hosts can use endpoints, repositories mirrored internally, or controlled egress if updates require it.

Repeat subnet tiers across Availability Zones

A resilient three-tier VPC commonly has public, private application, and private data subnets in at least two Availability Zones. The public subnets host internet-facing load balancer nodes or zonal NAT gateways, while application and data tiers are duplicated privately across zones.

Do not create one enormous public subnet and one enormous private subnet across a Region; a subnet cannot span Availability Zones. The AZ boundary is built into the subnet. Repeating the tier in each zone makes routing and failure behavior explicit.

Use consistent naming and tags that include environment, tier, and zone. When operators investigate a route or security incident, `prod-app-private-us-east-1a` communicates more than a random subnet identifier.

CIDR planning should reserve space for horizontal growth and managed-service interfaces. EKS pods using VPC IPs, ECS tasks in `awsvpc` mode, interface endpoints, load balancers, and RDS network interfaces can consume addresses quickly. A subnet that looked generous for fifty EC2 instances can become constrained when every task or pod needs its own address.

Separate route tables when egress behavior differs

Subnets that have different egress requirements should not share a route table merely to reduce objects. A public subnet needs a default route to an internet gateway. A private application subnet may need NAT or interface endpoints. A data subnet may need no default internet route at all.

Per-AZ route tables are often useful when private subnets use zonal NAT gateways so each subnet points to the local gateway. Regional NAT gateways can simplify that pattern for supported public NAT use cases, but the route table should still show the intended egress path clearly.

Keep the main route table conservative and use explicit associations for production subnets. This reduces the risk that a newly created subnet inherits an internet route or transit path unintentionally.

Route-table propagation from Transit Gateway, VPN, or other network constructs can make a subnet effectively connected to far more networks than its local table suggests at first glance. Review propagated and static routes together, and use segmentation controls at the transit layer so a private subnet does not become broadly reachable from every connected account or on-premises segment.

Use security groups as primary workload firewalls

Security groups are stateful and attach to resources such as EC2 instances, load balancers, and many managed interfaces. They are usually the primary mechanism for expressing which application components can communicate. Rules can reference other security groups, which is often clearer than broad CIDR ranges inside the VPC.

A common pattern allows the application tier to receive traffic only from the load balancer security group and the database to receive traffic only from the application security group. That relationship remains valid as instances scale and IP addresses change.

Network ACLs operate at the subnet boundary and are stateless. They can provide coarse-grained guardrails or explicit deny logic, but they require return-path rules and are usually less precise for application relationships. Use them deliberately rather than duplicating every security-group rule.

Security-group references work well inside supported boundaries, but cross-account and cross-VPC scenarios require awareness of peering, Transit Gateway, and resource sharing constraints. Do not replace a clear workload identity with `10.0.0.0/8` simply because a shared network is large. Narrow CIDRs, prefix lists, or service-specific controls can preserve intent.

Prefer private endpoints for supported AWS services

Private workloads often need S3, DynamoDB, ECR, Systems Manager, Secrets Manager, or other AWS APIs. VPC endpoints can keep supported service traffic on private AWS networking and avoid a public internet/NAT path. This reduces exposure and can also reduce NAT processing for high-volume service access.

Gateway endpoints and interface endpoints behave differently. Gateway endpoints add routes for supported services, while interface endpoints create private network interfaces and DNS integration for PrivateLink-powered services. Their pricing and policy controls differ, so choose based on traffic and service requirements.

Endpoint policies, service policies, IAM permissions, and security groups can all influence effective access. A private endpoint is a network path, not a replacement for authorization.

PrivateLink can expose a service privately to consumers without full VPC-to-VPC routing. This is useful when one team needs to publish a service to many accounts but does not want to create transitive network reachability. The service is reached through interface endpoints, and the provider keeps control of the specific load-balanced service rather than sharing its entire subnet space.

Plan IPv6 separately from IPv4

IPv6 resources do not use IPv4 NAT in the same way. A public IPv6 address is globally routable, so egress-only internet gateways can allow outbound IPv6 connections while blocking unsolicited inbound connections at the routing layer. Security groups remain critical for resource access.

Dual-stack applications need route tables, DNS, security groups, load balancers, and monitoring that understand both protocols. Do not add IPv6 CIDRs without deciding how each subnet’s ingress and egress model should work, because a private-by-IPv4 assumption does not automatically carry over to IPv6.

Address planning concepts from subnet masks and address design remain useful for IPv4, but modern VPC architecture should also reserve mental space for IPv6 rather than treating it as an afterthought.

IPv6 subnetting uses a different address scale, but the public/private distinction still depends on routing and ingress controls. A subnet with a route to an internet gateway can support public IPv6 communication, while an egress-only internet gateway supports outbound-only IPv6 initiation. Security groups should be reviewed for IPv6 rules rather than assuming IPv4 rules automatically cover both.

Validate reachability from the route outward

When connectivity fails, start with the source subnet route table and follow the packet path. Confirm the destination prefix, next hop, gateway attachment, security groups, NACLs, DNS resolution, and return route. This systematic approach is faster than changing security rules randomly.

VPC Flow Logs can show accepted and rejected traffic at network interfaces, while Reachability Analyzer can reason about supported paths. Load balancer logs and application logs add higher-layer evidence. The goal is to determine whether the problem is routing, filtering, name resolution, or the application itself.

For the broader SAP-C02 perspective, subnet design participates in Transit Gateway, inspection, hybrid connectivity, multi-account networking, and centralized egress. The same principle remains: call a subnet public or private because of its actual route path, and make every route reflect an intentional trust boundary.

Automated network validation can test intended reachability continuously. Reachability Analyzer, configuration rules, infrastructure-as-code policy checks, and route-table diff reviews can catch accidental public routes or broad security rules before they become incidents. Network architecture is easier to maintain when the expected paths are machine-verifiable rather than living only in diagrams.

(8, ‘Route-table design should also consider blackhole behavior. When a peering, transit, or gateway target is removed, stale routes can remain and become blackholes. Monitoring configuration state and testing critical destinations helps teams distinguish a deliberate private subnet from a subnet whose intended path is simply broken.’)

(8, ‘Private DNS can make endpoints feel transparent, but it also creates troubleshooting dependencies on Route 53 Resolver, resolver rules, and VPC DNS settings. When an application in a private subnet cannot reach a service, confirm name resolution before changing routes. A correct route to the wrong resolved address will still fail.’)

(8, ‘Do not use public IP absence as the only protection for management access. Systems Manager Session Manager, VPN, Direct Connect, or controlled bastion patterns can provide administrative paths without opening SSH or RDP to the internet. Security groups should restrict management traffic to the chosen control plane, and audit logs should record who initiated sessions.’)

(8, ‘As environments grow, consider IP address management across accounts and Regions. Overlapping VPC CIDRs complicate peering, Transit Gateway, and hybrid connectivity. AWS VPC IP Address Manager can help plan and track address allocations so subnet design remains compatible with future network integration rather than forcing expensive renumbering.’)

Public subnets should not become default landing zones for convenience. Infrastructure-as-code modules can make private placement the default and require an explicit flag for public IP assignment or internet-gateway routing. Defaults matter because most network exposure comes from routine provisioning choices repeated over time, not from one dramatic architectural decision.

Similarly, data subnets should be reviewed for lateral reachability, not only internet access. A subnet can be private from the internet yet broadly reachable from every internal VPC or corporate network. Transit routing, security groups, and database authorization should limit who can connect, because “private” is not synonymous with “trusted.”

Network diagrams should include route-table names and gateway targets, not just colored subnet boxes. A diagram that labels one zone “public” and another “private” without showing the actual default routes can become stale while configuration changes underneath it. Treat the route table as authoritative and generate or validate diagrams from infrastructure code where possible.

Review those assumptions after every network change.

Filed under Networking