I was recently asked what my preference is when interconnecting VPCs. Along with the question came context: a handful of VPCs in the same account, connecting to a Data VPC hosting a single RDS cluster.
The truth is, I wouldn’t have been able to give a useful answer without that context and additional knowledge I had about the AWS account, its VPCs, and the services running in them. “It depends” is the honest response to most architecture questions, but it’s not helpful. What’s helpful is knowing what it depends on.
AWS gives you three main options: VPC Peering, Transit Gateway, and PrivateLink. The docs explain what each one does. AWS even has a whitepaper on building scalable multi-VPC infrastructure. But these resources describe features and capabilities. They don’t tell you which option fits your situation. That’s what this post is for.
Start with constraints, not services
Before picking a tool, answer these questions:
- How many VPCs are you connecting? (2-3 vs 10+)
- Same account or cross-account?
- Same region or cross-region?
- What’s the trust relationship? (shared team vs service boundary)
- What kind of traffic? (databases, APIs, bulk data)
If you can’t answer these, you’re not ready to choose. Constraints eliminate options faster than preferences do.
The three patterns
VPC Peering: simple and explicit
Peering creates a direct network link between two VPCs. No transitive routing: if A peers with B and B peers with C, A can’t reach C through B.
This limitation is often cited as a downside. I’d argue it’s a feature. It keeps the blast radius small and makes the topology easy to reason about.
One hard constraint: peering requires non-overlapping CIDR ranges. If your VPCs have overlapping IP space, peering isn’t an option. This becomes a real problem in organizations that didn’t plan their IP addressing upfront, or when connecting VPCs that were built independently.
Use peering when:
- You have 2-4 VPCs in the same account
- Same region (cross-region peering works but adds latency)
- Teams share trust boundaries
- You want explicit, auditable connections
- Your CIDR ranges don’t overlap (and you’re confident they won’t)
Skip peering when:
- You’re connecting more than 4-5 VPCs (the mesh gets unwieldy)
- You need centralized routing control
- Cross-account with different trust levels
- You have or might have CIDR overlaps (look at PrivateLink instead)
Transit Gateway: platform-scale networking
TGW is a regional router. Attach your VPCs, define route tables, and traffic flows through a central hub. It handles cross-region, cross-account, and hybrid connectivity to on-prem networks.
TGW costs more than peering. You pay per attachment and per GB processed. But for growing platforms, the operational simplicity is worth it. One place to manage routes beats a mesh of peer connections.
Use TGW when:
- You have 5+ VPCs or expect to grow there
- You have a central VPC (shared services, networking, data platform) that others need to reach
- Hybrid connectivity to on-prem or other clouds
- You need centralized network policy
Skip TGW when:
- You have 2-3 stable VPCs (it’s overkill)
- Cost is the primary concern and traffic volume is high
- You need strict isolation between VPCs (PrivateLink might fit better)
PrivateLink: service boundaries, not networks
PrivateLink is different. It doesn’t connect networks. It exposes a service. You create an endpoint in your VPC that routes to a service in another VPC (or AWS account) without any network-level connectivity.
This matters when trust boundaries matter. The consumer VPC can’t route to anything except the exposed endpoint. No CIDR overlap concerns. No shared routing tables.
Use PrivateLink when:
- Cross-account access where you don’t control both sides
- You want to expose a service, not a network
- Strict isolation requirements (compliance, multi-tenant)
- Avoiding CIDR coordination entirely
Skip PrivateLink when:
- You need bidirectional connectivity
- High-throughput, low-latency east-west traffic
- The overhead of endpoint management isn’t worth the isolation
A note on databases
“Use PrivateLink for database access” is common advice, but it needs context.
If the database is a shared platform service, accessed by multiple teams across accounts with clear producer/consumer boundaries, PrivateLink makes sense. You’re treating the database as a service endpoint.
If the database is a component of a larger system with heavy east-west traffic between services in different VPCs, the per-connection overhead of PrivateLink adds up. Peering or TGW might be simpler.
Ask yourself: is this database a service or a component? That usually answers the question.
But what about a public NLB?
I get this question occasionally. Why bother with VPC connectivity at all? Just put a Network Load Balancer in front of the service and expose it.
Private NLBs still require VPC interconnection. They don’t solve the connectivity problem, they just give you a stable endpoint for PrivateLink or direct access within a peered network.
Public NLBs do solve the connectivity problem. A service in VPC-A can reach a public NLB in VPC-B without any peering, TGW, or PrivateLink setup. It works. But now your internal service is exposed to the internet.
I wouldn’t recommend this path for internal services. The attack surface is larger, and you’re relying on network-level controls (security groups, NACLs) to protect something that could have been isolated entirely.
The exception: if the service is meant to be public anyway. An API that external clients will consume, a webhook endpoint, a public-facing application. In that case, a public NLB is the right tool and VPC interconnection isn’t the problem you’re solving.
If you go the (not recommended) public NLB route for internal traffic anyway, at minimum:
- Restrict security groups to known source IPs or CIDR ranges
- Enable access logs and monitor them
- Use TLS termination at the NLB with valid certificates
- Treat this as a public endpoint in your threat model, because it is one
My defaults
I start with peering for small, same-account setups. Move to TGW when the VPC count grows past 4-5 or when I need centralized control. Use PrivateLink for cross-account service exposure where isolation matters.
Signals that make me reconsider:
- Cross-region requirements push toward TGW
- Compliance requirements around network isolation push toward PrivateLink
- Rapid growth expectations push toward TGW (easier to add VPCs than manage a peering mesh)
- Service is already public-facing? Then VPC interconnection isn’t the question. Use a public NLB and move on.
The “best” option is usually obvious once you’ve written down your constraints. If it’s not obvious, you’re probably missing a constraint.