Skip to main content

Transit Gateway and VPC Peering — Multi-Account Networking on AWS

· 7 min read
Goel Academy
DevOps & Cloud Learning Hub

You start with one VPC. Then you add a staging VPC. Then a shared-services VPC. Then three more teams each get their own accounts. Suddenly you have 8 VPCs that all need to talk to each other, and you've created a mesh of 28 VPC peering connections that nobody can draw on a whiteboard anymore. This is where Transit Gateway enters the picture.

VPC Peering — Simple but Limited

VPC Peering creates a direct network route between two VPCs. It's free (no hourly charge, you only pay for data transfer), it works cross-account and cross-region, and it's simple to set up:

# Create a peering connection from VPC-A to VPC-B
PEERING_ID=$(aws ec2 create-vpc-peering-connection \
--vpc-id vpc-aaa111 \
--peer-vpc-id vpc-bbb222 \
--peer-owner-id 987654321098 \
--peer-region us-west-2 \
--query 'VpcPeeringConnection.VpcPeeringConnectionId' --output text)

# Accept the peering in the other account/region
aws ec2 accept-vpc-peering-connection \
--vpc-peering-connection-id $PEERING_ID

# Add routes in BOTH VPCs (this is manual and easy to forget)
aws ec2 create-route --route-table-id rtb-aaa111 \
--destination-cidr-block 10.1.0.0/16 \
--vpc-peering-connection-id $PEERING_ID

aws ec2 create-route --route-table-id rtb-bbb222 \
--destination-cidr-block 10.0.0.0/16 \
--vpc-peering-connection-id $PEERING_ID

The limitations hit fast:

  • No transitive routing. If VPC-A peers with VPC-B, and VPC-B peers with VPC-C, then VPC-A cannot reach VPC-C through VPC-B. You need a direct peering between A and C.
  • Full mesh scaling problem. For N VPCs you need N(N-1)/2 peering connections. 5 VPCs = 10 connections. 10 VPCs = 45 connections. 20 VPCs = 190 connections.
  • No centralized routing. Each VPC manages its own route tables independently.
VPC CountPeering Connections NeededManageable?
33Yes
510Probably
1045Painful
20190No
501,225Absolutely not

Transit Gateway — The Hub-and-Spoke Solution

Transit Gateway (TGW) acts as a regional network hub. Every VPC attaches to the TGW, and the TGW handles routing between them. Instead of N(N-1)/2 connections, you have N attachments:

# Create a Transit Gateway
TGW_ID=$(aws ec2 create-transit-gateway \
--description "Central network hub" \
--options '{
"AmazonSideAsn": 64512,
"AutoAcceptSharedAttachments": "disable",
"DefaultRouteTableAssociation": "enable",
"DefaultRouteTablePropagation": "enable",
"DnsSupport": "enable",
"VpnEcmpSupport": "enable"
}' \
--query 'TransitGateway.TransitGatewayId' --output text)

# Attach VPC-A
aws ec2 create-transit-gateway-vpc-attachment \
--transit-gateway-id $TGW_ID \
--vpc-id vpc-aaa111 \
--subnet-ids subnet-a1 subnet-a2

# Attach VPC-B
aws ec2 create-transit-gateway-vpc-attachment \
--transit-gateway-id $TGW_ID \
--vpc-id vpc-bbb222 \
--subnet-ids subnet-b1 subnet-b2

# Attach VPC-C (in a different account via RAM — covered below)
aws ec2 create-transit-gateway-vpc-attachment \
--transit-gateway-id $TGW_ID \
--vpc-id vpc-ccc333 \
--subnet-ids subnet-c1 subnet-c2

Now VPC-A can reach VPC-B and VPC-C through the Transit Gateway, and VPC-B can reach VPC-C. No full mesh required.

TGW Route Tables — Segmented Routing

The real power of Transit Gateway is route table segmentation. You can create separate route tables to control which VPCs can talk to each other:

# Create a route table for production VPCs
PROD_RT=$(aws ec2 create-transit-gateway-route-table \
--transit-gateway-id $TGW_ID \
--query 'TransitGatewayRouteTable.TransitGatewayRouteTableId' --output text)

# Create a route table for development VPCs
DEV_RT=$(aws ec2 create-transit-gateway-route-table \
--transit-gateway-id $TGW_ID \
--query 'TransitGatewayRouteTable.TransitGatewayRouteTableId' --output text)

# Associate prod VPC with prod route table
aws ec2 associate-transit-gateway-route-table \
--transit-gateway-route-table-id $PROD_RT \
--transit-gateway-attachment-id tgw-attach-prod-vpc

# Propagate shared-services routes to BOTH route tables
# (so prod and dev can both reach shared services)
aws ec2 enable-transit-gateway-route-table-propagation \
--transit-gateway-route-table-id $PROD_RT \
--transit-gateway-attachment-id tgw-attach-shared-vpc

aws ec2 enable-transit-gateway-route-table-propagation \
--transit-gateway-route-table-id $DEV_RT \
--transit-gateway-attachment-id tgw-attach-shared-vpc

This means production VPCs can reach shared services but not development VPCs, and vice versa. Classic network segmentation without firewalls.

Multi-Account Connectivity With RAM

In an AWS Organizations setup, you share the Transit Gateway across accounts using Resource Access Manager (RAM):

# Share TGW with your entire organization
aws ram create-resource-share \
--name "shared-transit-gateway" \
--resource-arns "arn:aws:ec2:us-east-1:111111111111:transit-gateway/$TGW_ID" \
--principals "arn:aws:organizations::111111111111:organization/o-abc123" \
--allow-external-principals false

# In the other account, they can now attach their VPC
aws ec2 create-transit-gateway-vpc-attachment \
--transit-gateway-id $TGW_ID \
--vpc-id vpc-other-account \
--subnet-ids subnet-x1 subnet-x2

RAM can also share subnets, Route 53 resolver rules, License Manager configurations, and more across accounts.

VPN and Direct Connect Attachments

Transit Gateway can also terminate VPN connections and Direct Connect gateways, making it the single entry point for on-premises connectivity:

# Create a VPN attachment to TGW (instead of attaching VPN to a single VPC)
CUSTOMER_GW=$(aws ec2 create-customer-gateway \
--type ipsec.1 \
--public-ip 203.0.113.1 \
--bgp-asn 65000 \
--query 'CustomerGateway.CustomerGatewayId' --output text)

aws ec2 create-vpn-connection \
--type ipsec.1 \
--customer-gateway-id $CUSTOMER_GW \
--transit-gateway-id $TGW_ID \
--options '{"StaticRoutesOnly": false}'

Direct Connect provides a dedicated physical connection from your data center to AWS. It offers lower latency, consistent bandwidth (1 Gbps or 10 Gbps), and reduced data transfer costs compared to VPN over the internet. You associate a Direct Connect Gateway with your Transit Gateway to give on-premises access to all attached VPCs.

PrivateLink is fundamentally different from peering or TGW. Instead of connecting entire networks, it exposes a single service (behind an NLB) as a private endpoint in another VPC:

# Service provider: Create a VPC Endpoint Service
aws ec2 create-vpc-endpoint-service-configuration \
--network-load-balancer-arns arn:aws:elasticloadbalancing:us-east-1:111111111111:loadbalancer/net/my-service-nlb/abc123 \
--acceptance-required

# Service consumer: Create an interface endpoint to consume the service
aws ec2 create-vpc-endpoint \
--vpc-id vpc-consumer \
--vpc-endpoint-type Interface \
--service-name com.amazonaws.vpce.us-east-1.vpce-svc-abc123 \
--subnet-ids subnet-consumer-a \
--security-group-ids sg-endpoint

PrivateLink is ideal when you want to share a specific API or service without exposing your entire network. The consumer only sees an ENI in their VPC — they can't route to anything else in your network.

Network Architecture Patterns Comparison

PatternUse CaseScalabilityCostComplexity
VPC Peering2-3 VPCs, simple connectivityLow (full mesh)Low (data transfer only)Low
Transit Gateway4+ VPCs, hub-and-spokeHigh (5,000 attachments)Medium ($0.05/hr per attachment + $0.02/GB)Medium
PrivateLinkService-to-service, no network mergeHighLow-Medium ($0.01/hr + $0.01/GB)Low
TGW + Direct ConnectHybrid cloudHighHigh (DX port + TGW + data)High
TGW Inter-Region PeeringMulti-regionHighHigh (TGW + inter-region data)High
CloudWANGlobal network managementVery HighHighVery High

Cost Implications

Transit Gateway is not free, and the costs can add up:

  • TGW attachment: $0.05/hr per attachment ($36/month per VPC)
  • Data processing: $0.02/GB through the TGW
  • VPC Peering: $0.01/GB (same region), $0.02/GB (cross-region), no hourly fee

For two VPCs exchanging 500 GB/month in the same region:

  • VPC Peering cost: 500 GB x $0.01 = $5/month
  • TGW cost: (2 x $36) + (500 GB x $0.02) = $82/month

So if you only have 2-3 VPCs, peering is drastically cheaper. Transit Gateway pays for itself when you have 5+ VPCs and need centralized routing, segmentation, or on-premises connectivity.

What's Next

Networking determines how your services communicate, but how do those services authenticate? In the next post, we'll compare Secrets Manager, Parameter Store, and HashiCorp Vault — three approaches to managing the credentials your applications need to function securely.