Filter concepts by levelShowing all levels.

AWS · Subnets, Routing, and Gateways

Subnets, Routing, and Gateways

Sizing a subnet, deciding where its traffic goes, and which of three outbound paths it should actually take

  • 5 IPs always reservedusable count is 2^(32−prefix) − 5, /28 to /16 allowed
  • Route table decides egresslocal route is automatic; default route picks the path
  • NAT is outbound-onlystructurally — no inbound path exists through it
  • Endpoints skip NAT entirelyfree for S3/DynamoDB, billed for everything else

1.Subnet CIDR planning and IP allocation

A subnet's CIDR size decides how many IP addresses it holds — but AWS reserves 5 addresses in every subnet, so a /28 (16 addresses) really only has 11 usable, not 16.

Key features

  • AWS reserves the first 4 and the last address in every IPv4 subnet — 5 total
  • Those 5: network address, VPC router, DNS (base+2), future use, broadcast
  • IPv4 subnets must be between /28 (smallest) and /16 (largest)
  • Each subnet is pinned to exactly one Availability Zone
  • Subnets cannot be resized after creation without creating a new one

Common subnet sizes and their usable IP count (5 always reserved)

Common subnet sizes and their usable IP count (5 always reserved)
CIDRTotal addressesUsable addresses
/24256251
/25128123
/266459
/273227
/281611 — smallest AWS allows
A /28 subnet — 16 addresses, only 11 usable

def usable_ips(prefix_len): total = 2 ** (32 - prefix_len) return total - 5 # AWS reserves 5 addresses in every subnet print(usable_ips(28)) # 11

2 ** (32 - prefix_len)

total addresses — /28 → 16 total addresses in the block

total - 5

usable = total − 5 — network, router, DNS, future-use, and broadcast are always reserved

  • Whole: def usable_ips(prefix_len): total = 2 ** (32 - prefix_len) return total - 5 # AWS reserves 5 addresses in every subnet print(usable_ips(28)) # 11
  • 2 ** (32 - prefix_len) — total addresses: /28 → 16 total addresses in the block
  • total - 5 — usable = total − 5: network, router, DNS, future-use, and broadcast are always reserved

Command

text
usable IPs = 2^(32 - prefix) - 5

Every AWS subnet reserves exactly 5 addresses — usable count is 2^(32 − prefix) − 5, not the raw block size, and smaller subnets lose a proportionally bigger share to that reservation.

2.Route-table associations and egress paths

Every subnet is associated with exactly one route table (the VPC's main table, unless explicitly changed), and that table's routes — most importantly the default route — decide where traffic leaving the subnet actually goes.

Key features

  • A subnet not explicitly associated uses the VPC's main route table
  • A "local" route (the VPC's own CIDR) is automatically present and cannot be removed
  • The default route (0.0.0.0/0) decides where traffic outside the VPC goes
  • An internet gateway route makes a subnet public; a NAT gateway route keeps it private but outbound-capable
  • A NAT gateway itself must live in a public subnet to reach the internet gateway

What a subnet's default route points at

What a subnet's default route points at
Default route targetEffect
Internet gateway (igw-...)Public — inbound and outbound internet
NAT gateway (nat-...)Private — outbound-only internet, no inbound
No default route presentFully isolated — no internet path either direction
A private subnet's outbound path
outboundtrafficdefaultrouteNAT's own subnetroutes here

Private subnet

Route table

0.0.0.0/0 → NAT gateway

NAT gateway

lives in a public subnet

Internet gateway

  • Private subnet
    • leads to Route table (outbound traffic)
  • Route table — 0.0.0.0/0 → NAT gateway
    • leads to NAT gateway (default route)
  • NAT gateway — lives in a public subnet
    • leads to Internet gateway (NAT's own subnet routes here)
  • Internet gateway

Command

text
Route table:
  10.0.0.0/16 → local          (automatic, cannot be removed)
  0.0.0.0/0   → igw-xxx | nat-xxx | (absent)

The local route (auto-present, unremovable) guarantees intra-VPC connectivity; the default route (0.0.0.0/0) decides egress — internet gateway makes it public, NAT gateway keeps it private but outbound-capable.

3.Inbound reachability vs outbound-only access

A private subnet with a NAT gateway can reach the internet (outbound) — download a package, call an external API — but the internet can never initiate a connection back in. That asymmetry is the entire reason private subnets exist.

Key features

  • A NAT gateway allows outbound connections and their return traffic — nothing else
  • An unsolicited inbound connection from the internet is never allowed through a NAT gateway
  • This is different from a security group's stateful "return traffic" — NAT is about the initiator's direction, not just packet state
  • A public subnet with an internet gateway allows both directions, if security group/NACL rules permit
  • Database and internal-service subnets are almost always private for exactly this reason

Command

text
Private subnet, outbound via NAT:
  app → api.example.com     ✓ initiated from inside
  internet → app            ✗ never allowed in, regardless of port

A NAT gateway is structurally outbound-only — it allows a private subnet to call out and receive the response, but there is no path for the internet to initiate a connection in, regardless of security group settings.

4.VPC endpoints: gateway vs interface

A VPC endpoint lets a private subnet reach an AWS service (like S3 or DynamoDB) without going through a NAT gateway or the public internet at all — the traffic stays entirely inside AWS's network.

Key features

  • Gateway endpoints: S3 and DynamoDB only, added as a route-table target, no extra cost
  • Interface endpoints: most other AWS services, an ENI with a private IP in your subnet, billed hourly
  • Neither type sends traffic through a NAT gateway or internet gateway
  • A gateway endpoint is referenced via a prefix list in the route table, not a fixed IP
  • An interface endpoint gets its own private DNS name that overrides the public service endpoint

Gateway endpoint vs interface endpoint

Gateway endpoint vs interface endpoint
PropertyGateway endpointInterface endpoint
ServicesS3, DynamoDB onlyMost other AWS services
ImplementationRoute-table target (prefix list)ENI with a private IP, PrivateLink
CostNo additional chargeHourly + data processing charges
Reachable fromSame VPC onlyVPC, plus on-prem via Direct Connect/VPN
Gateway endpoint vs interface endpoint

Gateway endpoint

  • S3, DynamoDB only
  • A route-table target (prefix list)
  • No additional charge

Interface endpoint

  • Most other AWS services
  • An ENI with a private IP + PrivateLink
  • Billed hourly + data processing
  • Gateway endpoint
    • S3, DynamoDB only
    • A route-table target (prefix list)
    • No additional charge
  • Interface endpoint
    • Most other AWS services
    • An ENI with a private IP + PrivateLink
    • Billed hourly + data processing

Command

text
Without an endpoint: private subnet → NAT gateway → internet gateway → S3 (public endpoint)
With a gateway endpoint: private subnet → S3, entirely inside AWS's network

Gateway endpoints (S3, DynamoDB — free, route-table based) and interface endpoints (most other services — billed, DNS + ENI based) both keep traffic off the NAT gateway and off the public internet entirely.

5.NAT gateway cost and architecture tradeoffs

A NAT gateway bills by the hour it exists AND by every gigabyte of data it processes — one per AZ for high availability adds up fast, and traffic that could have used a free VPC endpoint instead pays the data-processing rate for no reason.

Key features

  • A NAT gateway has an hourly charge, whether or not it processes any traffic
  • It also charges per GB of data processed, on top of the hourly charge
  • One NAT gateway per AZ is the standard highly-available pattern — multiplying the hourly cost by AZ count
  • A single shared NAT gateway is a single point of failure for that AZ's outbound access
  • S3/DynamoDB traffic routed through a gateway endpoint instead avoids NAT processing charges entirely

Command

text
NAT gateway cost = (hourly rate × hours running) + (per-GB rate × data processed)

NAT gateways bill hourly AND per-GB — one per AZ (not per subnet) is the standard resilient pattern, and a gateway endpoint removes S3/DynamoDB traffic from the NAT bill entirely.

Remember

  • Every subnet reserves exactly 5 addresses — plan from usable count, not the raw CIDR block size.
  • The local route is automatic and unremovable; the default route (0.0.0.0/0) decides internet reachability.
  • A NAT gateway is structurally outbound-initiated-only — no security group setting changes that.
  • A gateway endpoint for S3/DynamoDB is free and takes that traffic off the NAT gateway's billed data path.

Pro tip

  • Size subnets for Auto Scaling and rolling-deployment headroom, not just today's instance count.
  • One NAT gateway per Availability Zone (not per subnet) is the standard resilient, cost-sane pattern.
  • A route table can be shared by several subnets — check associations before assuming a change is scoped to one.

Next up

  • Security Groups and Network ACLs
  • DNS and Network Connectivity
  • Load Balancing

Sources

  • Subnet CIDR blocks — docs.aws.amazon.com/vpc/latest/userguide/subnet-sizing.html
  • VPC endpoints — docs.aws.amazon.com/vpc/latest/privatelink
  • Checked against official AWS documentation 2026-08-21

Spotted a mistake on this page? Tell us.