Skip to content

Route tables, and why there is no NAT

2 min read · main part only; folded sections are optional

After this you can answer: How does traffic know where to go, and how does MiniTickets work without a NAT gateway?

flowchart LR
subgraph PUB["public route table"]
L1["10.0.0.0/16 → local"]
D1["0.0.0.0/0 → internet gateway"]
end
subgraph PRIV["private route table"]
L2["10.0.0.0/16 → local"]
end
D1 --> IGW["minitickets-dev-igw"] --> NET((Internet))
  1. Every route table has the local route. 10.0.0.0/16 → local means any address inside the VPC is reachable. AWS adds it by itself.
  2. The most specific route wins. A packet to 10.0.10.5 matches both /16 local and /0; the /16 is more specific, so it stays inside the VPC.
  3. An internet gateway connects the VPC to the internet, but only for resources with a public IP, and only if a security group rule allows the traffic.
  4. A NAT gateway would let private resources call out without a public IP. Postgres and Valkey never start outbound connections, so they do not need one.

Both tables are made in infra/src/network.ts → createNetwork: minitickets-dev-public-rt (associated with both public subnets) and minitickets-dev-private-rt (both private subnets). The gateway is minitickets-dev-igw.

How the tasks reach AWS services without a NAT: they run in the public subnets with a public IP, so ECR, Secrets Manager, CloudWatch Logs and SNS are reached through the internet gateway, over HTTPS. The other common fix, VPC endpoints, also costs money per hour and per zone.

From → toWhat happensWhat allows it
Public subnets → Public route tableboth public subnets use this route table
  • route route table associations minitickets-dev-public-rta-1 and -2createNetwork
Public route table → Internet gatewaytraffic for the internet leaves through the internet gateway
  • route route 0.0.0.0/0 → minitickets-dev-igw (next to the local route 10.0.0.0/16)createNetwork
See stage 2 on the map →

VPC → Route tables → minitickets-dev-public-rt → Routes: 0.0.0.0/0 → igw-…, Status Active. Then Subnet associations.

SymptomCauseWhere to look
The site times out from every networkThe 0.0.0.0/0 route is missing or BlackholePublic route table → Routes
One zone works, the other does notA public subnet is not associated with the public tableSubnet associations
A task moved to a private subnet cannot pull its imageNo NAT and no VPC endpointPrivate route table: local only
When would you add a NAT gateway?

When tasks must run in private subnets, for example a policy that no compute has a public IP. Then each zone needs a NAT gateway (or VPC endpoints for the AWS services the tasks call).

What is the difference between a NAT gateway and an internet gateway?

An internet gateway lets resources with a public IP talk in both directions. A NAT gateway lets resources with only a private IP start connections out, and blocks connections in.

What happens if the internet gateway is detached?

The 0.0.0.0/0 route becomes Blackhole. Visitors time out, and new tasks cannot pull images or read secrets, so they fail to start.

Advanced: Why VPC endpoints were not chosen

Interface endpoints for ECR (two), Secrets Manager, CloudWatch Logs and SNS would each be billed per hour per availability zone, and S3 needs a gateway endpoint. For one dev task that is more than the task itself costs. The public-IP design keeps the bill small; the security groups do the protecting.

Answer these without scrolling up. If one feels hard, reread that section.

  1. Which route does every route table have?
  2. Which route wins when two match?
  3. What two more things does traffic need besides the 0.0.0.0/0 route?
  4. How do the tasks reach ECR without a NAT gateway?
  5. Why do Postgres and Valkey not need any way out?

Redraw it from memory: the two route tables, their routes, and the internet gateway

Try this: in the AWS console or on the map, find the one route that makes the public subnets public

Read this book online: https://book.theversehub.in/