When to Use Private and Public Subnets in the Cloud?

Aug 29 / Irina Zarzu
Overview
 
In the early stages of cloud adoption, it may seem tempting to place all the resources into a single subnet and rely entirely on well-configured security groups.

While this approach may look simple and easy to maintain, it’s a trap I’ve seen teams (especially startups) fall into, due to the lack of info or specialized team members. To enhance security and to reduce the attack surface on your workloads, you must approach a defense-in-depth strategy.

Following AWS best practices, one of the most important design patterns in AWS networking is the segregation of subnets into private and public. Public is for controlled entry points; private is for workloads and data.

In this article, I will walk you through how different AWS services and resources use public vs. private subnets, the risk of relying only on security groups, and why subnet-level segmentation plays a foundational role in a secure, scalable, and compliant cloud architecture.
Private Subnet vs. Public Subnet

Before we dive into details, I would like to talk a bit about the limitations in today's world.
In real world, "public vs. private" runs into three main constrains: IP scope, limited address pools, and segmentation.

First, IPv4 is scarce and everyone reuses the same RFC1918 blocks (10/8, 172.16/12, 192.168/16). 
The catch I’ve seen on client projects: the moment you need VPC peering, a Transit Gateway, or a partner VPN, CIDRs overlap, routing breaks, and you’re choosing between NAT band-aids or painful renumbering.

Secondly, every subnet has a limited number of IP addresses. They can be consumed really fast when you scale out, in blue / green environments, or add a new AZ. What helped me is treating IPs like a capacity metric: track them, alert early, and allocate with them wisely. AWS recommends using VPC IP Address Manager (IPAM) to plan, track, monitor IP addresses for your AWS workloads.

Third, network segmentation isolates parts of the network and help you protect sensitive assets, where data resides. From my perspective, this is the most underestimated part of the configuration. While it reduces the attack surface and limits lateral movement, it must be carefully planned (tiered subnets, strict security groups, governed egress) to make it harder for an attacker to move freely through the environment.

A subnet is a logical separation of IP addresses in your VPC, where you can deploy resources
such as EC2, ECS, Lambda, RDS.

A key difference between them is access to the Internet.
• A public subnet has access to the Internet through an Internet Gateway and is
associated with a public routing table.
Public subnets are typically used for resources that need direct access to the Internet, such as
Load Balancers, Ingress Controllers, NAT Gateways, proxies or host bastions.
• A private subnet, on the other hand, it does not have direct Internet access, and it is
associated with a private route table.
Private subnets host internal services, databases, EC2 instances, EKS pods.

A non-negotiable detail is that each subnet lives entirely within a single Availability Zone and never spans AZs. In practice, high availability means creating one subnet per AZ for each tier, placing resources across them, and using per-AZ components (NAT, load balancers) to avoid cross-AZ dependencies. 

From a security perspective, public subnets are more exposed to external threats due to their
internet connectivity. If resources are deployed in public subnet with an Elastic IP, they are
publicly reachable even though security groups are configured.
In contrast, resources in private subnets are more protected, and the malicious attacker should
bypass other security layers to get to the private resources.

How AWS Resources Use Subnets

1. Load Balancers and Subnets


Load Balancers handle incoming requests from users across multiple targets to ensure high
availability and performance.
Depending on the use case, Load Balancers can be either public (internet-facing) or private
(internal).
A public load balancer is deployed in public subnets, with a public IP address and configured
with routes to the Internet Gateway. It handles incoming traffic from external users and
forwards requests to internal resources such as web servers.
A private load balancer is deployed in private subnets, without any route to Internet Gateway. It
handles incoming traffic received from web servers to backend application servers or
microservices, ensuring traffic remains within the VPC boundary.

Choose the type based on the traffic. Use an Application Load Balancer (ALB) for HTTP/HTTPS with host or path routing, WebSockets, and Kubernetes Ingress. Use a Network Load Balancer (NLB) for TCP/UDP or TLS pass-through when you need very low latency, static IPs, or to preserve the original connection. Use a Gateway Load Balancer (GWLB) when you must send traffic through inspection appliances such as firewalls or IDS in an inspection VPC.

Another protection layer that should not be forgotten: enforce TLS everywhere. Use for the ALB listener ACM certificates and redirect HTTP to HTTPS; if the application requires it, re-encrypt to the targets or use NLB TLS pass-through. Keep security groups tight: public ALBs expose only the required ports to the internet; internal load balancers accept traffic only from trusted sources; targets allow inbound only from the load balancer’s security group - never 0.0.0.0/0. Anytime you see 0.0.0.0/0 on a backend SG, stop and ask who really needs this.

Best practice that 's gaining more traction and I wholeheartedly embrace, it is to drop bastions and use AWS Systems Manager Session Manager: no inbound SSH, short-lived, IAM-governed sessions with full audit in CloudTrail/SSM logs; when you need admin access (e.g., to a database), use SSM port-forwarding instead of opening ports.

Furthermore, keep traffic on the AWS backbone by using VPC endpoints: Gateway Endpoints for S3 (and DynamoDB) and Interface Endpoints (PrivateLink) for ECR, STS, and Secrets Manager. This way, requests don’t traverse the public internet, reducing both egress risk and cost.

Add AWS WAF for common exploit protection and rate limiting, and consider mTLS when clients must authenticate.

2. Lambda VPC based and Subnets 
AWS Lambda is a serverless compute service that help you run code in response to events, automatically scaling and managing compute resources, without managing servers.
Here’s the bit I wish someone told me on day one: by default, AWS Lambda functions run outside your VPC with access to the internet. However, when a Lambda needs to connect to resources inside the VPC (EC2 instances, RDS databases, private APIs), it must be configured to run within that VPC and placed in specific subnets.

When assigned to a private subnet, the Lambda function does not have direct internet access. If the function needs to call external services (third-party APIs, AWS services without VPC endpoints, or downloading packages during execution), a NAT Gateway in a public subnet is required to route that outbound traffic.

Placing a Lambda in a public subnet does not give it internet access, because Lambda functions never receive public IPs. Even in a public subnet, outbound internet traffic requires a NAT Gateway. For accessing AWS services privately (without internet), use VPC endpoints. For inbound requests from users, invoke the function via a Lambda Function URL, Amazon API Gateway, or an Application Load Balancer.

3. Kubernetes and Subnets

Microservices architectures deployed with Kubernetes, such as Amazon EKS, require proper network segmentation to ensure security, scalability and traffic management.  Public subnets are usually used for internet-facing components such as Ingress Controllers behind load balancers, as well as NAT Gateway that allow private subnets to have internet connectivity.

In contrast, private subnets host internal components like EKS worker nodes, internal services, and running Pods. While these workloads are isolated from direct public access, they still need access to the Internet to pull container images from registries like ECR or DockerHub and to interact with external APIs. This is achieved routing traffic through a NAT Gateway in a public subnet.

Kubernetes leverages subnet tagging and annotations to determine where load balancers should be provisioned. For example, specifying alb.ingress.kubernetes.io/scheme: internet facing directs the controller to use public subnets, while alb.ingress.kubernetes.io/scheme: internal ensures internal access only. With the AWS VPC CNI plugin, Pods are assigned native VPC IPs, which means that IP capacity in private subnets directly affects scaling.

As a best practice, workloads should reside in private subnets, with public subnets reserved for controlled ingress and NAT traffic, with all the communication tightly managed by security groups.


4. Transit Gateway and Subnets

AWS Transit Gateway is a centralized hub that acts as a virtual router for interconnecting multiple VPCs, on-premises networks and VPNs. 

When attaching a VPC to a Transit Gateway, you must specify one subnet per Availability Zone for the attachment. In each specified subnet, TGW places an Elastic Network Interface, enabling traffic routing to and from the Transit Gateway.

Transit Gateway is primarily used for private subnets where resources need to communicate with resources from another VPCs or on prem networks. The traffic is routed directly through the Transit Gateway, and not through Internet Gateway. This keeps flows on the AWS backbone and reduces exposure to the public internet.

It is highly recommended to create dedicated subnets for Transit Gateway attachments. This prevents Transit Gateway ENIs from being deployed into the same subnets where application resources reside, helping to maintain clean network boundaries and simplify security management.


5. Databases and subnets

Databases store sensitive information and customer information, making them the main target for data breaches and data exfiltration attempts. 

To reduce the risk of unauthorized access, as a best practice, it is to deploy databases in private subnets within a VPC. Since private subnets are not accessible from the internet, you ensure another layer of isolation, keeping your data secure.

In addition, use a DB security group that allows inbound traffic only from the backend server’s security group and on the DB port. Never use 0.0.0.0/0 on inbound rules. Enforce TLS for all connections so traffic to the database is encrypted in transit.

Use IAM authentication where supported, this gets rid of static passwords and replaces them with short-lived auth tokens. If IAM auth isn’t available, store credentials in AWS Secrets Manager with rotation enabled (don’t hardcode secrets). It saves you from the “who rotated the prod password?” fire drills.

Turn on encryption at rest with KMS for the database and snapshots/backups. Manage key access with least privilege and enable rotation where it makes sense. My rule of thumb: if someone doesn’t need to decrypt, they don’t get the key.

Inside the database, apply least privilege principle: separate roles for the application and for admins, grant only the permissions the app needs, and log/audit changes. The moment you need to investigate, good logs are worth their weight in gold.

By isolating databases from public exposure and adding encryption, strict security groups, TLS, Secrets Manager, and least-privilege access, organizations can better protect data and comply with security and compliance standards.


Conclusion 

Designing a secure AWS environment starts with defining network boundaries, and subnet segmentation is one of the most effective ways to enforcing those boundaries.

When we place each component: load balancers, databases, Kubernetes/EKS nodes and pods, Lambda functions, Transit Gateways, in the right kind of subnet, we reduce the attack surface, and strengthen the overall security posture.

The public vs private subnets it is a tricky subject even for experienced cloud practitioners. The simple rule of thumb I use on client work is:

Public = controlled ingress traffic & NAT only.
Private = workloads & data.

Everything else, such as security groups, NACLs, VPC Endpoints, IAM authentication / conditions exist to enforce those boundaries.

Mastering these patterns will also help in your AWS certification preparation, as subnet design appears across AWS certifications.

Next up, we’ll go deeper into network segmentation: security groups, NACLs, IAM Access Control Based on IP Address.
Created with