AWS Transit Gateway
Transit Gateway (TGW) is a regional, managed router for VPCs, VPNs, and Direct Connect. It replaces the mesh-of-peering anti-pattern with a hub-and-spoke topology — the closest AWS-native equivalent to an MPLS core. Essential the moment you have more than a handful of VPCs.
Why it exists
VPC Peering is non-transitive. If VPC-A peers with VPC-B, and VPC-B peers with VPC-C, A cannot reach C via B. To mesh N VPCs with peering you need N·(N-1)/2 peerings — quickly unmanageable past ~5 VPCs.
Transit Gateway is the transitive alternative:
┌──────┐ ┌──────┐
│ VPC-A │ │ VPC-B │
└───┬──┘ └──┬───┘
│ │
└──────┬───────┘
│
┌─────▼─────┐
│ TGW │ ← routes between attachments
└─────┬─────┘
│
┌──────────┴──────────┐
│ │
┌───▼───┐ ┌─────▼─────┐
│ VPC-C │ │ VPN/DX to │
│ │ │ on-prem │
└───────┘ └───────────┘
Each VPC attaches once; routing policy lives in TGW route tables.
Core objects
| Object | What it is |
|---|---|
| Transit Gateway | The regional router itself. One TGW can serve the whole account or be shared via RAM. |
| Attachment | A link between the TGW and something else: a VPC, a VPN, a Direct Connect Gateway, a peering to another TGW, or a Connect attachment (GRE/BGP). |
| TGW Route Table | The forwarding table. A TGW has one default route table; you typically create more. |
| Association | Pins an attachment to exactly one TGW route table — determines “which routes does this attachment see?” |
| Propagation | A separate switch that lets an attachment advertise its routes into a TGW route table — determines “which attachments contribute routes?” |
Association and propagation are separate knobs — this is how you build segmentation (see below).
How routing works
- Traffic enters TGW via an attachment (e.g. from VPC-A)
- TGW looks up the destination in the associated route table of that attachment
- Longest-prefix-match picks the next-hop attachment
- Packet is forwarded out that attachment
Each attachment also has a VPC-side route table change: to send traffic to TGW, the VPC’s subnet route table needs a route like 10.0.0.0/8 → tgw-xxxx. TGW appears as a valid route target.
Segmentation via route tables
Classic multi-environment pattern — isolate prod from dev while both talk to shared services:
TGW Route Tables:
RT-Prod : associated with prod VPCs (propagates: prod + shared)
RT-Dev : associated with dev VPCs (propagates: dev + shared)
RT-Shared : associated with shared-svcs (propagates: all)
Result:
- Prod can reach Shared, but not Dev
- Dev can reach Shared, but not Prod
- Shared can reach everything
This is L3 microsegmentation at the inter-VPC level — the clean way to do multi-account, multi-env networking.
Cross-region with TGW Peering
Two TGWs in different regions can peer (attachment type: TGW peering). Traffic crosses the AWS backbone encrypted. Peering is point-to-point and non-transitive at the TGW level — if you chain three regions via peering, you still need explicit routes on each.
For large-scale multi-region, AWS Cloud WAN is the newer, policy-driven evolution.
Attachments in depth
VPC attachments
- Create an ENI in each AZ’s subnet you pick (one subnet per AZ is enough; the ENI services that whole AZ)
- AZ-affinity for traffic: TGW tries to keep traffic in the same AZ — cross-AZ inside TGW only if the destination VPC has no attachment in the source AZ
- Can’t share a subnet between the attachment ENI and EC2 instances — use a small dedicated
/28
VPN attachments
- IPsec Site-to-Site VPN terminates on TGW instead of a Virtual Private Gateway (VGW)
- BGP (dynamic) or static routes
- Two tunnels per VPN for redundancy; use ECMP on TGW (enable “Equal-Cost Multi-Path”) to load-balance across both
Direct Connect attachment
- Actually attaches a Direct Connect Gateway (DXGW) which fronts the DX link
- BGP carries customer prefixes into TGW
Connect attachments
- A GRE-over-VPC tunnel from a third-party appliance (SD-WAN, NVA) to TGW
- BGP inside the GRE for dynamic routing
- Used when you’re running Cisco/Aviatrix/Palo Alto/etc. in a transit VPC
TGW peering
- Inter-region, inter-account — stitch regions together
Sharing across accounts (RAM)
A TGW is an account-local resource, but via AWS RAM (Resource Access Manager) it can be shared with other accounts in the same Organization. Attach their VPCs, they see no TGW config — just a route target. This is how you build a centralised network account with spoke accounts attaching their VPCs.
Split of concerns:
- Network account: owns TGW, DX, VPN, route tables
- Workload accounts: own VPCs, attach to shared TGW via RAM
Inspection and appliance insertion
Put a firewall/NVA in a dedicated “inspection VPC” and force traffic through it using appliance-mode attachments. Appliance mode pins flows to a single ENI (prevents asymmetric routing across AZs inside the inspection VPC) so stateful appliances see both directions of every flow.
The pattern:
Spoke VPC → TGW → Inspection VPC (firewall) → TGW → other spoke
TGW route tables hairpin through the inspection VPC via route-table tricks.
Cost model
TGW is not free. Two dimensions:
- Per-attachment-hour (VPC attachments are the typical multiplier — charged while attached)
- Per-GB of data processed through TGW
At scale, TGW data charges can become a noticeable line item. Traffic that stays within a VPC doesn’t traverse TGW and doesn’t count. The cost math sometimes favours VPC Peering for a small number of chatty VPCs.
Limits worth knowing
- 5000 attachments per TGW
- 10,000 routes per route table
- 50 Gbps per attachment per AZ (aggregate can be higher with multiple AZs)
- 5 TGWs per region per account (soft limit)
Common pitfalls
- Attachment-subnet chosen in the wrong AZ. Traffic destined to an AZ without an attachment crosses AZs inside TGW — surprise charges and latency.
- Overlapping CIDRs between VPCs. TGW won’t route to overlapping prefixes; each prefix must be globally unique within a route table.
- Forgot the VPC subnet route. TGW attaches cleanly, but VPC workloads still can’t reach remote prefixes because the subnet route table has no
→ tgw-xxxxentry. - Asymmetric routing through inspection VPC when appliance-mode isn’t enabled.
- Security groups referencing by SG ID — SG-referencing doesn’t work across TGW; use CIDRs or prefix lists.
- Propagation vs. association confusion. If an attachment associates with RT-X but doesn’t propagate into RT-X, it can consume the RT but won’t be advertised as a destination — nobody can reach it.
Mental model for a network engineer
- TGW ≈ MPLS PE in a service-provider core. Attachments are CE-facing circuits; TGW route tables are VRFs; RAM-sharing is a tenant’s circuit into the provider.
- Association = which VRF is this attachment in. Propagation = which VRFs import this attachment’s routes.
- Peering = inter-AS link between TGWs in different regions.
- Connect = a stretched GRE/BGP session to integrate SD-WAN overlays.