Skip to content

VPC peering vs PrivateLink — full reachability or service-only, and which one your partner actually wants

Peering connects two VPCs at the network layer. PrivateLink exposes one service across that line. The choice changes who has to handle CIDR overlap, DNS, and least privilege.

A partner integration starts with a casual ask: “can we get private connectivity to your API?” The default response is to set up a VPC peering, exchange CIDRs, update route tables on both sides, and ship. Three months later the partner’s audit team flags the peering as overbroad — they have full network-layer reachability into your VPC, and the security control on what they can touch is “we hope they only call the load balancer.” The peering was the wrong primitive. The right one is PrivateLink — it exposes a single service across the boundary and nothing else. Here is the line between the two, and how to pick correctly the first time.

What’s happening

VPC peering is a network-layer connection between two VPCs. Once peered, instances in VPC A can reach IPs in VPC B’s CIDR range (subject to route tables and security groups), and vice versa. Peering is symmetric — both sides see the other side’s CIDR. Peering is non-transitive — A peered to B and B peered to C does not give A reach to C. Peering is region-aware — inter-region peering exists and is billed at inter-region transfer rates. The cost is hourly per peering plus data transfer.

The capabilities peering gives you:

  • Full IP reachability into the peer VPC’s CIDR.
  • The ability for any instance in either VPC to initiate a connection to any IP in the other.
  • DNS resolution of the peer VPC’s private DNS, if you enable it explicitly.

The capabilities peering does not give you:

  • Service-level access control. Once peered, an instance in the peer VPC can nmap your entire CIDR. The only enforcement is per-instance security groups, which means you have to maintain SG rules across the boundary.
  • CIDR overlap tolerance. Two VPCs with overlapping CIDRs cannot be peered.
  • Cross-account simplicity. Peering across accounts works, but the security control surface is “they have a route to your VPC” which is rarely what your security team wants.

AWS PrivateLink is a service-layer connection. The service provider (you) puts a Network Load Balancer in front of the service you want to expose, then creates a VPC endpoint service that points at that NLB. The service consumer (your customer or partner) creates an interface endpoint in their VPC pointing at your endpoint service. Their instance now resolves a regional hostname (vpce-xxx.us-east-1.vpce.amazonaws.com or a private DNS name like api.yourdomain.com if you enable private DNS) to the endpoint’s ENI in their VPC. Traffic flows from their VPC across PrivateLink to your NLB to your service. The two VPCs are not peered. Their VPC sees only the one service you exposed. Your VPC sees only the requests coming in via the NLB.

The capabilities PrivateLink gives you:

  • Service-only exposure. The consumer reaches one TCP port on one NLB, nothing else.
  • CIDR overlap tolerance. The two VPCs can have identical 10.0.0.0/16 CIDRs and it works — the endpoint ENI lives in the consumer’s IP space, and the NLB owns the destination on your side. No CIDR negotiation.
  • Per-consumer authorization. Each customer’s account gets explicit acceptance to use your endpoint service. The consumer’s account ID is the IAM principal you grant.
  • DNS that just works. The consumer’s SDK calls api.yourdomain.com; private DNS resolves it to the endpoint ENI; the call lands on your service. No /etc/hosts hack, no peer DNS resolution flag.

The capabilities PrivateLink does not give you:

  • Full reachability. If you have five services, you need five endpoint services (or one NLB with five target groups, which works for HTTPS-only setups but constrains the protocol). PrivateLink is the wrong primitive when the connectivity model is “general-purpose network reachability.”
  • Symmetric flow. The consumer calls the provider. The provider cannot initiate to the consumer. For a request/response API this is fine; for a webhook callback the provider has to find a public path (which negates the point).

How to verify

The decision frame is “what is the actual connectivity requirement?”

RequirementPeeringPrivateLink
Same-org, two VPCs that need to fully talkyesoverkill
Cross-account API exposure to a customeroverbroadyes
SaaS provider exposing one API to many customerswrong (every customer sees every other’s CIDR? no, peerings are point-to-point but the auth model is wrong)yes
Customer consuming a SaaS API privatelydepends on provider; if they offer it, prefer PrivateLinkyes if provider supports
Shared services VPC reachable from multiple environmentsTGW, not peering or PrivateLinknot the right tool
CIDR-overlapping VPCsimpossibleworks
Database access across accountsoverbroad; consider it the wrong choiceyes
Bidirectional general trafficyesimpossible

The single most common pivot we see: a B2B SaaS that started by setting up VPC peering with each customer (because “private connectivity” was the ask and peering was the first answer they knew). Six customers in, the peering CIDRs collide; CIDR negotiation becomes a sales blocker; the security team flags that customer A’s peered VPC can technically reach customer B’s traffic via a shared bastion. The fix is to expose the API via a PrivateLink endpoint service. Each customer creates a one-way endpoint into the SaaS’s VPC. CIDR overlap is irrelevant. Customer A cannot see customer B. The endpoint service authorization list is the IAM-style access control.

The other pivot: the customer side. Consuming a SaaS via PrivateLink instead of public internet is worth doing when:

  • The SaaS supports it.
  • The data sensitivity justifies the operational cost of one more endpoint per AZ.
  • The customer is large enough that the egress-cost savings on cross-region traffic justify the hourly endpoint cost.

For most small SaaS-to-customer integrations, public HTTPS with API keys is simpler. PrivateLink is the right answer at the enterprise end of the customer base where “no public internet path” is a real requirement.

The fix

The decision procedure for a new private connectivity requirement:

  1. Ask “what is the connectivity for?” If the answer is “we want their app servers to call our API,” that is service-only. PrivateLink. If the answer is “we want full reachability between our two VPCs for an integration that will grow,” that is network-layer. Peering or TGW.

  2. Ask “how many parties?” Two VPCs, same org, will not grow: peering is fine. Three or more, same org: TGW. One service exposed to many parties: PrivateLink. The peering vs PrivateLink decision is fundamentally about whether the connectivity is many-to-one (PrivateLink) or two-to-two (peering).

  3. For the PrivateLink provider setup:

    # 1. NLB in front of the service
    aws elbv2 create-load-balancer \
      --name api-private-nlb \
      --type network \
      --scheme internal \
      --subnets subnet-prod-1a subnet-prod-1b subnet-prod-1c
    
    # 2. Endpoint service pointing at the NLB
    aws ec2 create-vpc-endpoint-service-configuration \
      --network-load-balancer-arns arn:aws:elasticloadbalancing:us-east-1:111122223333:loadbalancer/net/api-private-nlb/abc123 \
      --acceptance-required \
      --private-dns-name api.example.com
    
    # 3. Allow specific customer accounts
    aws ec2 modify-vpc-endpoint-service-permissions \
      --service-id vpce-svc-abc123 \
      --add-allowed-principals arn:aws:iam::555566667777:root
  4. For the PrivateLink consumer setup (in the customer’s account):

    aws ec2 create-vpc-endpoint \
      --vpc-endpoint-type Interface \
      --vpc-id vpc-customer123 \
      --service-name com.amazonaws.vpce.us-east-1.vpce-svc-abc123 \
      --subnet-ids subnet-customer-1a subnet-customer-1b subnet-customer-1c \
      --security-group-ids sg-allow-app-to-endpoint \
      --private-dns-enabled

    The --private-dns-enabled flag makes api.example.com resolve to the endpoint ENI from within the customer’s VPC. This requires the provider to have verified the domain (DNS TXT record) and the customer to have enableDnsHostnames and enableDnsSupport on their VPC.

  5. For peering, when it is genuinely the right tool:

    # Request the peering from VPC A's account
    aws ec2 create-vpc-peering-connection \
      --vpc-id vpc-a-123 \
      --peer-vpc-id vpc-b-456 \
      --peer-owner-id 555566667777 \
      --peer-region us-east-1
    
    # Accept from VPC B's account
    aws ec2 accept-vpc-peering-connection \
      --vpc-peering-connection-id pcx-abc123
    
    # Add routes both sides
    aws ec2 create-route \
      --route-table-id rtb-a-private \
      --destination-cidr-block 10.30.0.0/16 \
      --vpc-peering-connection-id pcx-abc123

    Update security groups on both sides to allow the specific traffic that matters. The default is to allow nothing — peering opens the route, SGs open the conversation.

The migration from peering to PrivateLink is straightforward once the NLB is in place: spin up the endpoint service, have the customer create the endpoint, cut over their DNS to the private endpoint name, watch for a week, tear down the peering. The hardest part is convincing the customer’s team that the change is worth doing — usually it requires a security review that flags the peering as overbroad first.

The other rule we hold: PrivateLink is the right primitive for SaaS-to-customer integrations, full stop. Even if the first customer would have been fine with peering, the second one will have a CIDR collision and the third will have an audit finding. Starting with the endpoint service is the lower-cost path.

For the multi-VPC story when both sides are inside the same org, see Transit Gateway hub-and-spoke. For the cost-of-egress side of the endpoint decision, see VPC endpoints — gateway and interface.


Stack Harbor designs PrivateLink and peering topologies for SaaS-to-customer and intra-org connectivity as part of Managed AWS and ongoing Managed Cloud Ops. If your customer integrations are running on overbroad peerings, start with an infrastructure consult.