Subnets and Route Tables in Depth
~14 min read
How a route table's target field is the single source of truth for whether a subnet is public or private.
Every VPC gets a 'main' route table by default, automatically associated with any subnet that doesn't have a more specific route table explicitly attached. Best practice is to never leave critical subnets on the main route table — create explicit route tables per subnet tier (one for all public subnets, one for all private subnets) so intent is clear and accidental changes to the main table don't silently affect everything.
Each route table entry has a destination CIDR and a target. The 'local' route (destination = the VPC's own CIDR, target = local) is added automatically and can't be removed — it's what lets resources within the VPC talk to each other regardless of subnet. Every other route you add is explicit: a 0.0.0.0/0 route to an Internet Gateway makes a subnet public; a 0.0.0.0/0 route to a NAT Gateway gives a subnet outbound-only internet access while remaining unreachable from outside.
Multiple subnets can share the same route table — you don't need one route table per subnet, just one per distinct routing behavior you need (e.g. 'public-rt' shared by all public subnets across every AZ, 'private-rt' shared by all private subnets).
💬 Deep Dive with AI
Key points
- •The 'local' route is automatic and lets resources in the VPC reach each other regardless of subnet
- •A subnet is public or private purely based on its route table's 0.0.0.0/0 target — not a label or setting
- •Best practice: explicit route tables per tier, never leave production subnets on the default main route table
- •Multiple subnets across AZs can share one route table if they need identical routing behavior