Definition
- Route Table – An ordered set of rules (routes), each mapping a destination CIDR to a target such as
local, IGW, NAT Gateway, peering connection, Transit Gateway, or VPC endpoint. - Subnet Association – Every subnet is associated with exactly one route table; the association determines the subnet's forwarding behavior.
- Local Route – An unremovable route for the VPC's own CIDR that keeps all internal traffic within the VPC.
- Longest-Prefix Match – The forwarding rule where AWS picks the route with the most specific (longest) matching prefix for each packet.
- Main Route Table – The default route table for a VPC; subnets without an explicit association use it.
A route table is the signpost board at National Bank of India that tells every letter where to go next based on its destination address. Addresses inside this building? Stay internal (local). Addresses out on the street? Go to the front door (Internet Gateway) or the mailroom (NAT). Addresses in the partner's building across the road? Take the private bridge (peering). The most specific signpost wins.
Understanding the Concepts
What is a route table?
A route table is a set of routes, where each route maps a destination CIDR block to a target. Every VPC has a main route table created automatically, and you can create custom route tables and associate them with specific subnets. A subnet always has exactly one route table; the association determines its forwarding behavior.
# Create a custom route table for private subnets
aws ec2 create-route-table --vpc-id vpc-0abc
# Output: rtb-private
# Associate it with a subnet
aws ec2 associate-route-table --route-table-id rtb-private --subnet-id subnet-private-a
What is the local route?
Every route table has an unremovable local route for the VPC's own CIDR. This means all subnets in a VPC can always reach each other internally without any extra configuration. You cannot delete or modify this route.
# Every route table starts with: 10.0.0.0/16 → local (VPC internal traffic – always present, cannot be removed)
How do route tables make subnets public or private?
A subnet is public when its route table has a 0.0.0.0/0 route pointing to an Internet Gateway. A subnet is private when that route points to a NAT Gateway or does not exist. The route table is the sole mechanism that determines public vs private.
# Public subnet route table 10.0.0.0/16 → local (VPC internal) 0.0.0.0/0 → igw-0abc123 (two-way internet) ← PUBLIC # Private subnet route table (outbound via NAT) 10.0.0.0/16 → local 0.0.0.0/0 → nat-0gateway (outbound only) ← PRIVATE # Isolated subnet route table (no internet at all) 10.0.0.0/16 → local # No default route ← FULLY ISOLATED
How does longest-prefix match work?
When a packet needs to be forwarded, AWS looks at all routes that match the packet's destination and picks the one with the most specific (longest) prefix. This is deterministic and predictable.
# Application private subnet route table 10.0.0.0/16 → local (VPC internal) 172.16.0.0/16 → pcx-0peer123 (peered VPC) 0.0.0.0/0 → nat-0gateway (outbound internet via NAT) # Packet to 172.16.5.9: # Matches 172.16.0.0/16 (/16 = 16 bits) # Matches 0.0.0.0/0 (/0 = 0 bits) # Longest prefix wins → pcx-0peer123 (peering link) # Packet to 8.8.8.8: # Matches 0.0.0.0/0 only → nat-0gateway (internet via NAT) # Packet to 10.0.5.20: # Matches 10.0.0.0/16 → local (stays in VPC)
How do route tables enable VPC peering?
To communicate between peered VPCs, both sides need route table entries. VPC A's route table needs a route for VPC B's CIDR pointing to the peering connection, and VPC B's route table needs the reverse.
# VPC A (10.0.0.0/16): add route to VPC B
aws ec2 create-route --route-table-id rtb-vpc-a \
--destination-cidr-block 172.16.0.0/16 \
--vpc-peering-connection-id pcx-0peer123
# VPC B (172.16.0.0/16): add route back to VPC A
aws ec2 create-route --route-table-id rtb-vpc-b \
--destination-cidr-block 10.0.0.0/16 \
--vpc-peering-connection-id pcx-0peer123
# BOTH routes required – missing either means one-way communication
How do route tables work with Transit Gateway?
A Transit Gateway is a hub that connects multiple VPCs and on-premises networks. Each VPC's route table has a route pointing to the Transit Gateway for destinations reachable through it.
# VPC route table with Transit Gateway 10.0.0.0/16 → local 10.1.0.0/16 → tgw-0abc (to staging VPC via Transit Gateway) 10.2.0.0/16 → tgw-0abc (to dev VPC via Transit Gateway) 0.0.0.0/0 → nat-0xyz (outbound internet)
Why is routing two-way?
Routing is a two-way conversation. For VPC A to communicate with VPC B, A needs a route to B and B needs a route back to A. If only one side has the route, requests arrive but replies are silently dropped because there is no return path. Forgetting the return route is the most common cause of mysterious one-way connectivity failures.
public class TwoWayRouting {
// WRONG: only VPC A has a route to VPC B
// A sends request → arrives at B
// B tries to reply → no route to A → packet dropped silently
// Result: connection times out
// CORRECT: both VPCs have routes to each other
// A → route to B via peering → B receives
// B → route to A via peering → A receives reply
}
What are common mistakes?
The first mistake is forgetting the return route in a peering or Transit Gateway setup. Traffic flows one way but replies are silently dropped.
The second mistake is confusing route tables with firewalls. Route tables control where traffic goes, not whether it is allowed. Security Groups and NACLs control the allow/deny.
The third mistake is associating the wrong route table with a subnet, accidentally making a private subnet public or vice versa.
# Check which route table a subnet is using
aws ec2 describe-route-tables \
--filters "Name=association.subnet-id,Values=subnet-0abc" \
--query 'RouteTables[*].Routes'
# Verify the routes match your intent (public vs private)
What should a senior engineer know?
A senior engineer knows that route tables and firewalls are separate concerns. Routes determine reachability (can the packet get there?), while Security Groups and NACLs determine permission (is the packet allowed?). They troubleshoot connectivity by checking both independently.
They also know about more-specific routes for edge cases: a /32 route for a specific IP overrides any less-specific route, which is useful for sending traffic for one host through a different path. And they know that the maximum number of routes per table is 50 by default (can be increased to 1,000).
# Senior troubleshooting checklist:
1. Route table: does a route exist for the destination? (reachability)
2. Is the route pointing to the correct target? (correct path)
3. Does the return route exist on the other side? (two-way)
4. Security Group: does it allow the traffic? (permission)
5. NACL: does it allow both directions? (permission, stateless)
Visual Overview
┌──────── Route Table Traffic Control ────────┐ │ │ │ Route Table for Private App Subnet: │ │ ┌────────────────────────────────────┐ │ │ │ 10.0.0.0/16 → local (VPC) │ │ │ │ 172.16.0.0/16 → pcx-peer (peer) │ │ │ │ 0.0.0.0/0 → nat-gw (NAT) │ │ │ └────────────────────────────────────┘ │ │ │ │ Packet to 10.0.5.20: │ │ └── Matches 10.0.0.0/16 → local (VPC) │ │ │ │ Packet to 172.16.5.9: │ │ └── Matches 172.16.0.0/16 → peering │ │ (more specific than 0.0.0.0/0) │ │ │ │ Packet to 8.8.8.8: │ │ └── Matches 0.0.0.0/0 → NAT Gateway │ │ │ │ Two-way requirement: │ │ VPC A → route to B ✓ │ │ VPC B → route to A ✓ │ │ Both needed, or replies are dropped │ └──────────────────────────────────────────────┘
Key Takeaway
A route table is an ordered set of routes, where each route maps a destination CIDR to a target – that target can be local, an Internet Gateway, a NAT Gateway, a VPC peering connection, a Transit Gateway, or a VPC endpoint. Every subnet is associated with exactly one route table, and that association determines the subnet's behaviour, including whether it is public or private. Every route table also has an unremovable local route for the VPC's own CIDR, which is why all subnets in a VPC can always reach each other internally.
The way route tables control traffic is through longest-prefix match. When a packet needs to be forwarded, AWS looks at all the routes that match the destination and picks the most specific one. So if a table has a route for the peered VPC's range and also a default 0.0.0.0/0 route to a NAT Gateway, a packet bound for the peer matches the more specific route and crosses the peering link, while a packet bound for the internet only matches the default route and goes out through NAT.
In a banking VPC this is how one subnet reaches many destinations. At National Bank of India our application subnet's route table keeps traffic to other internal subnets local, sends traffic for the analytics VPC across a peering connection, and sends everything else outbound through a NAT Gateway for patches.
The two senior points I always make are these. First, a route table decides where traffic is sent but not whether it is allowed – Security Groups and NACLs decide that, so routing and firewalling are separate concerns. Second, routing is a two-way conversation: for VPC A to talk to VPC B, A needs a route to B and B needs a route back to A, and forgetting the return route is the most common cause of one-way connectivity failures.
Remember one sentence: A route table maps destination CIDRs to targets using longest-prefix match, and the route determines where traffic goes while Security Groups determine whether it is allowed.
---