Sri BalajiBeyond the basic VPC: private connectivity to services, peering vs Transit Gateway, hybrid links to on-prem, and DNS that actually resolves across the
⚡ TL;DR: Go past the basic VPC: connect privately to services with PrivateLink, choose peering versus Transit Gateway, link on-prem over VPN or Direct Connect, and make DNS actually resolve across the boundary.
You built a VPC. Subnets are carved up, route tables are clean, the NAT gateway works, and your app reaches the internet. Then a real requirement lands: "Reach the managed database, but never over the public internet." "Connect this VPC to four others without a tangle of peerings." "Let the on-prem payroll system call our internal API." "Make db.internal.acme.com resolve the same from a Lambda, an EC2 box, and a server in the data center." Suddenly the basic VPC mental model runs out of road.
This is the layer where cloud networking stops being about one VPC and starts being about connectivity between things, services, VPCs, and your own data center, plus the DNS that ties them together. Get it right and traffic stays private, predictable, and cheap. Get it wrong and you either expose internal systems to the internet or spend a day staring at a name that won't resolve.
📌 Who this is for: Engineers who already understand a single VPC (subnets, route tables, security groups) and now need private service access, multi-VPC topologies, hybrid links to on-prem, and DNS that works across all of it. New to VPCs? Start with Cloud Networking Fundamentals: How a VPC Actually Works first.
Advanced cloud networking is just deciding which pipes connect which buildings, and making sure every building uses the same phone book.
The whole article in one line
Every option below is a different shape of pipe, and DNS is the shared phone book. Before the cloud-specific names overwhelm you, anchor on the physical picture:
| In the real world | In tech |
|---|---|
| A private hallway between two adjacent offices | VPC peering, direct, 1:1, non-transitive |
| A central transit hub every office connects to once | Transit Gateway, hub-and-spoke for many VPCs |
| A service window into a shop, no street access | PrivateLink / Private Service Connect, reach one service privately |
| An armored tunnel to your old headquarters | VPN / Direct Connect / ExpressRoute, hybrid to on-prem |
| The shared phone book every building trusts | Private DNS zones, internal names that resolve everywhere |
Cloud networking primitives mapped to a city of buildings.
Here is the topology most senior cloud engineers end up building. An application VPC reaches a managed service privately through PrivateLink, connects to other VPCs through a Transit Gateway, and reaches the on-prem data center over Direct Connect or a VPN, while a private DNS resolver makes internal names resolve from every side.
App VPC reaches a service via PrivateLink, peers VPCs through a Transit Gateway, links on-prem via Direct Connect/VPN, and resolves internal names via a private resolver.
PrivateLink (AWS) and Private Service Connect (GCP) solve one precise problem: reach a single service over private IP space without peering whole networks together. The provider exposes the service behind a load balancer; you create an endpoint in your VPC that materializes as a network interface (an ENI) with a private IP in your own subnet. Your traffic to that IP is tunneled to the service, no internet gateway, no public IP, no route changes between networks.
The win over peering is isolation and scale. Peering joins entire address spaces and forces you to manage overlapping CIDRs and bidirectional trust. PrivateLink exposes only the one service and is one-directional, the consumer reaches the provider, never the reverse. It is how you consume a SaaS vendor, another team's internal API, or an AWS service (S3, Secrets Manager) without your packets ever touching public routes. The trade-off: it is per-service, so it does not replace VPC-to-VPC routing for general traffic.
VPC peering is a direct, point-to-point link between two VPCs. It is cheap and low-latency, but it is non-transitive: if A peers with B and B peers with C, A still cannot reach C. With N VPCs that all need to talk, you face N·(N-1)/2 peerings, a full mesh that becomes unmanageable past a handful.
Transit Gateway (AWS) / Cloud Router + VPC peering hubs (GCP) is a hub-and-spoke router. Each VPC attaches once to the hub, and the hub routes between all of them, and to on-prem over the same attachment model. It costs more (per-attachment and per-GB) and adds a hop, but it turns an O(N²) mesh into O(N) attachments and gives you one place to apply route tables and segmentation. Rule of thumb: 2-3 VPCs that rarely change, use peering; a growing fleet or anything hybrid, use a Transit Gateway.
| Pattern | Joins | Transitive? | Best when | Watch out for |
|---|---|---|---|---|
| VPC Peering | Two VPCs, full CIDRs | No | 2-3 stable VPCs, lowest cost/latency | Mesh explosion; overlapping CIDRs block it |
| Transit Gateway | Many VPCs + on-prem via a hub | Yes (per route table) | Growing fleet, central segmentation, hybrid | Per-attachment + data cost; extra hop |
| PrivateLink / PSC | Consumer → one service | N/A | Consume a SaaS/internal API/AWS service privately | Per-service only; one-directional |
| VPN / Direct Connect | Cloud ↔ on-prem | Via TGW/router | Reaching the data center | VPN = internet-dependent; DX = lead time + cost |
Pick the connectivity pattern by what you are actually joining.
Hybrid means joining your cloud network to your physical data center. Two grades exist. A site-to-site VPN runs an encrypted IPsec tunnel over the public internet, fast to stand up, cheap, but latency and throughput ride on the open internet, so it varies. Direct Connect (AWS) / ExpressRoute (Azure) / Cloud Interconnect (GCP) is a dedicated private circuit from a carrier into the cloud provider, consistent latency, higher bandwidth, lower per-GB cost at scale, but weeks of lead time and a monthly port fee.
The common production pattern is both: Direct Connect as the primary path for predictable performance, with a VPN as automatic failover if the circuit drops. Routes are usually exchanged via BGP, so each side learns the other's prefixes dynamically, which is exactly why your CIDR planning has to be disjoint from day one (more on that in mistakes).
Here is a minimal Terraform setup: an interface endpoint (PrivateLink) for a service, plus a private hosted zone so a friendly internal name resolves to it. Scope this to your VPC and private subnets.
privatelink.tf
# Interface VPC endpoint (PrivateLink) into the provider's service
resource "aws_vpc_endpoint" "svc" {
vpc_id = aws_vpc.app.id
service_name = "com.amazonaws.vpce.eu-west-1.vpce-svc-0abc123"
vpc_endpoint_type = "Interface"
subnet_ids = aws_subnet.private[*].id
security_group_ids = [aws_security_group.endpoint.id]
private_dns_enabled = true # service's own DNS name now resolves to the ENI
tags = { Name = "svc-privatelink" }
}
# Lock the endpoint down: only the app tier may reach it on 443
resource "aws_security_group" "endpoint" {
name = "privatelink-endpoint"
vpc_id = aws_vpc.app.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
security_groups = [aws_security_group.app.id]
}
}
private-dns.tf
# Private hosted zone, internal names that never leak to public DNS
resource "aws_route53_zone" "internal" {
name = "internal.acme.com"
vpc {
vpc_id = aws_vpc.app.id # zone is only visible inside this VPC
}
}
# Friendly alias pointing at the PrivateLink endpoint
resource "aws_route53_record" "db" {
zone_id = aws_route53_zone.internal.zone_id
name = "db.internal.acme.com"
type = "A"
alias {
name = aws_vpc_endpoint.svc.dns_entry[0]["dns_name"]
zone_id = aws_vpc_endpoint.svc.dns_entry[0]["hosted_zone_id"]
evaluate_target_health = true
}
}
💡 Verify before you trust it: From an instance inside the VPC, run
dig db.internal.acme.com, it must return a private (RFC 1918) address, not a public one. Thennc -vz db.internal.acme.com 443. If dig returns a public IP, your private DNS orprivate_dns_enabledisn't wired up.
DNS is where hybrid setups quietly fall apart, because there are three name spaces, cloud private zones, on-prem internal zones, and the public internet, and every resolver has to know which one to ask for a given name.
A private zone (Route 53 private hosted zone / Cloud DNS private zone) is a DNS zone visible only inside the VPCs you associate with it. db.internal.acme.com resolves to a private IP for anything in the VPC and does not exist on the public internet. This is how you give services stable internal names without ever exposing them.
Split-horizon means the same name returns different answers depending on who asks. api.acme.com resolves to a private endpoint when queried from inside the VPC, and to a public load balancer when queried from the internet. You achieve it by running a public zone and a private zone for the same domain; the private zone wins for in-VPC queries. It is powerful, one hostname everywhere, but it is the single most confusing failure mode when someone debugs from the wrong network and gets the "other" answer.
For cloud and on-prem to resolve each other's names you need a resolver with forwarding rules: an inbound endpoint so on-prem can query cloud names, and an outbound endpoint with a conditional forwarder that says "send *.corp.local queries to the on-prem DNS server at 10.10.0.53." Without these, an instance in AWS asking for an on-prem hostname gets NXDOMAIN even though the network path is wide open.
10.0.0.0/16 cannot be peered or routed together, routing is ambiguous. Plan a disjoint IP address scheme across every VPC and data center before you build anything. This is the #1 retrofit nightmare.0.0.0.0/0 security-group rule because "it was faster than PrivateLink." Internal APIs and databases should only ever be reachable over private paths, PrivateLink, peering, or the Transit Gateway.api.acme.com from your laptop (public answer) while the app inside the VPC gets the private answer, and concluding the app is broken. Always check which network the failing query came from.The whole article in seven lines
Build the muscle memory hands-on, then zoom out to how this fits a real multi-account organization.
Originally published on TheSimplifiedTech, where this guide is interactive, with in-browser terminal labs and diagrams. Learn cloud and DevOps by doing, no videos.