AWS PrivateLink has long been the go-to solution for private connectivity of services within a region. Until recently, sharing services across regions required VPC peering or transit gateways — and sometimes even the creation of “outpost” VPCs to serve as transit VPCs. All that changes with the native Cross-Region PrivateLink solution.

Before December 2024, if you wanted a private interface endpoint in Region B for a service hosted in Region A, you have two options:

The widely used approahe was the the coupling of the peering and privatelink by :

1 — Deploying three VPCs

  1. Service Provider in Region A/ us-east-1
  2. Service Provider Outpost (Transit VPC) Region B/ us-west-2
  3. Service Consumer in Region B/ us-west-2

2 — Peer the Outpost VPC back to the Provider VPC (Peering supports cross regions peering connections)

3 — Register a Network Load Balancer (NLB) in the Outpost VPC as a VPC Endpoint Service

4 — Create an Interface VPC Endpoint in the Consumer VPC pointing at that service

Image

While this approach works well, it adds cost , complexity , and latency. You’re maintaining extra VPCs, NAT gateways, peering connections — and aligning AZs across regions.

On 11 December 2024 , AWS announced Cross‑Region Connectivity for PrivateLink :

_“With native cross‑region PrivateLink, service providers and consumers can share and access endpoint services across different Regions — without stitching together peering or Transit Gateways.” — _** _George Oakes, Devin Taylor & Wafa Adeel, _**AWS Blog

Introducing Cross-Region Connectivity for AWS PrivateLink | Amazon Web Services

What’s Changed?

  • No Transit VPC or peering required
  • Single NLB anchored in the service’s home region
  • Interface endpoints in any other region — just like in‑region endpoints
  • Automatic AZ alignment and health‑aware routing across regions

Image

🔗 For a full, step-by-step walkthrough of creating the VPCs, NLB, target group, listener, and in-region Interface Endpoint in Terraform, see “AWS Inter-Region PrivateLink using Terraform” (Nov 26 2023), and “How Does AWS PrivateLink Work ?” (Nov 20, 2023).

If you’ve ever stood up a same-region PrivateLink service (anf if not you can refer to the previous articles above 😀), this is nearly identical. The only change is the new supported_regions argument on your aws_vpc_endpoint_service—it tells AWS which remote regions may consume your service.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    provider "aws" {
      alias  = "provider"
      region = "us-east-1"
    }

    # … (VPC, subnet, NLB, target group, listener) …

    resource "aws_vpc_endpoint_service" "privatelink" {
      provider                   = aws.provider
      network_load_balancer_arns = [aws_lb.nlb.arn]
      acceptance_required        = false

      # 🔑 NEW: list any regions that can create endpoints for this service
      supported_regions          = ["eu-west-1"]
    }

    data "aws_caller_identity" "current" {}

    # Allow your own account to consume the service
    resource "aws_vpc_endpoint_service_allowed_principal" "self" {
      provider                = aws.provider
      vpc_endpoint_service_id = aws_vpc_endpoint_service.privatelink.id
      principal_arn           = data.aws_caller_identity.current.arn
    }

    output "privatelink_service_name" {
      value = aws_vpc_endpoint_service.privatelink.service_name
    }

Then, in your consumer region (eu-west-1 in this example), create an Interface Endpoint exactly as you would in-region:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
   provider "aws" {
     alias  = "consumer"
     region = "eu-west-1"
   }

   # … (Consumer VPC, subnet, SG) …

   resource "aws_vpc_endpoint" "cross_region" {
     provider            = aws.consumer
     vpc_id              = aws_vpc.consumer.id
     subnet_ids          = aws_subnet.consumer.*.id
     vpc_endpoint_type   = "Interface"
     service_name        = aws_vpc_endpoint_service.privatelink.service_name
     security_group_ids  = [aws_security_group.consumer_sg.id]
     private_dns_enabled = false
   }

   output "cross_region_endpoint_dns" {
     value = aws_vpc_endpoint.cross_region.dns_entries[0].dns_name
   }

That’s it! No Transit VPC, no peering, no AZ-alignment headaches — just exactly the same Terraform you know, with one extra list of regions.

⚙️ As usual, here’s an example of how to configure privatelink between two different regions and expose an EC2 machine through it:

aws-morocco-samples/native-cross-region-privatelink at main · Z4ck404/aws-morocco-samples

AWS PrivateLink Native Cross‑Region Connectivity was originally published in AWS Morocco on Medium, where people are continuing the conversation by highlighting and responding to this story.