Cloud Tech by Victor
DevOpsIntermediate

Cloud Networking Fundamentals

How virtual private clouds, subnets, and security groups model network isolation in the cloud, and why "public" vs "private" subnet is a routing decision, not a labeling one.

Updated 2026-07-223 min read

Overview

A virtual private cloud (VPC) is a logically isolated network within a cloud provider, and everything about how traffic flows in, out, and around it is governed by explicit configuration: subnets divide the VPC's address space, route tables decide where traffic destined outside a subnet goes, and security groups/network ACLs filter what's allowed at the resource and subnet level. The recurring point of confusion is that "public" and "private" aren't inherent properties of a subnet; they're just descriptions of what its route table currently does, which means auditing actual routes (not subnet names) is the only reliable way to know what's actually internet-reachable.

Quick Reference

ConceptPurposeScope
VPCLogically isolated virtual networkAccount/region-wide container
SubnetAddress-space subdivision of a VPCAvailability zone
Route tableDetermines where traffic destined outside a subnet goesPer subnet
Security groupStateful, per-resource allow-list firewallAttached resources
Network ACLStateless, subnet-wide allow/deny rulesPer subnet

Syntax

hcl
resource "aws_subnet" "private" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.2.0/24"
}

resource "aws_route" "private_nat" {
  route_table_id         = aws_route_table.private.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id          = aws_nat_gateway.main.id
}

Examples

hcl
# Security group - stateful, per-resource. Allowing inbound 443
# automatically permits the matching outbound response traffic.
resource "aws_security_group_rule" "https_in" {
  type              = "ingress"
  from_port         = 443
  to_port           = 443
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.web.id
}

Trust route tables, not subnet names

A subnet named "private-subnet" with a route to an internet gateway is still public, regardless of its name. Always verify actual route table entries when auditing what's internet-reachable, naming conventions are not enforcement.

Visual Diagram

Common Mistakes

  • Trusting a subnet's name ("private-subnet-1") instead of checking its actual route table; the two can silently disagree after a configuration change.
  • Placing a resource that only needs outbound internet access directly in a public subnet with a public IP, exposing it to inbound traffic it never needed to accept.
  • Over-relying on security groups alone and never using network ACLs as a defense-in-depth layer, or conversely, fighting stateless NACL rules without understanding why return traffic needs its own explicit allow.
  • Forgetting that a security group allowing 0.0.0.0/0 inbound on a sensitive port is a standing exposure, not a temporary convenience, if left in place after testing.

Performance

  • NAT gateways have their own throughput limits and per-GB data processing cost, very high-outbound-traffic workloads behind a single NAT gateway can hit real bottlenecks and cost, which is why multi-AZ NAT gateway placement matters at scale.
  • VPC peering and transit gateway routing add hops between networks, designing the topology (hub-and-spoke vs. full mesh) affects both latency and the blast radius of a routing misconfiguration.
  • Security group rule evaluation is effectively free at request time; it's a configuration correctness concern, not a runtime performance one.

Best Practices

  • Audit actual route tables, not subnet naming conventions, when determining what's genuinely internet-reachable.
  • Put anything that doesn't need to accept inbound internet traffic in a private subnet behind a NAT gateway for outbound access only.
  • Use security groups as the primary per-resource control and network ACLs as a coarser, subnet-wide defense-in-depth layer, not the other way around.
  • Design VPC topology (peering, transit gateway) deliberately for the traffic patterns you actually have, rather than defaulting to a full mesh that's harder to audit as it grows.

Interview questions

What makes a subnet "public" versus "private" in a cloud VPC?

It is entirely determined by routing, not by any label or flag on the subnet itself. A subnet is "public" if its route table sends traffic destined for the internet (0.0.0.0/0) to an internet gateway. A subnet is "private" if that route instead points to a NAT gateway (for outbound-only internet access) or has no internet route at all. Two subnets can be configured identically in every other respect and differ only in that one route table entry, which is why auditing actual route tables matters more than trusting subnet names like "public-subnet-1."

What is the difference between a security group and a network ACL?

A security group is stateful and attached to individual resources (like an instance or load balancer), if you allow inbound traffic on a port, the corresponding outbound response is automatically allowed, and rules are evaluated as an allow-list only. A network ACL is stateless and attached to a subnet, evaluating both inbound and outbound rules independently for every packet, including explicit deny rules. Security groups are the primary, more commonly used tool for per-resource access control; network ACLs add a coarser, subnet-wide layer, often left at their permissive default and used mainly for defense-in-depth or to explicitly block something.

Why would you use a NAT gateway instead of just putting a resource in a public subnet?

A NAT gateway lets resources in a private subnet initiate outbound connections to the internet (to pull a package, call an external API) while remaining unreachable from the internet for inbound connections; the NAT gateway only translates and forwards traffic the private resource itself initiated. Putting a resource directly in a public subnet with a public IP makes it directly reachable from the internet in both directions, which is unnecessary exposure for anything that only needs outbound access, like an application server that doesn't need to accept direct public traffic.

References

ShareXLinkedInReddit
Was this page helpful?
Suggest an improvement