skip to content

How would you publish an internal service running behind a Network Load Balancer so that consumers in other AWS accounts can reach it privately over AWS PrivateLink, and what are the tradeoffs of that model?

level: principalimportance: nice to knowfreq 30%

answer

  1. provider side needs a load balancer
  2. consumers dial, you never dial back
  3. allow-list plus an acceptance gate
  4. overlapping address ranges stop mattering
  5. the client's real IP does not survive

basics

~20 s

Front the service with a Network Load Balancer, create a VPC endpoint service from it, and allow specific consumer principals. Each consumer creates an interface endpoint in their own VPC. Connectivity is one-way, consumer to provider, and overlapping CIDRs do not matter.

solid answer

~60 s

On the provider side I put the service behind an NLB, create a VPC endpoint service configuration pointing at that load balancer, decide whether new connections require manual acceptance, and add the consumer account principals to the allow-list. Each consumer then creates an interface endpoint for my service name, which gives them an ENI in their own subnets. The appeal is isolation: the link is strictly one-way — consumers reach me, I cannot reach into their VPC — the two networks are never routed together, so overlapping CIDR ranges are irrelevant and no route or prefix has to be agreed. The tradeoffs are real. It is a per-service pipe, so many services mean many endpoint services or a shared ingress design; consumers pay for their endpoints and I pay for the NLB; the service must be TCP-fronted; my targets see the connection sourced from PrivateLink rather than the consumer's real client, so identifying the caller needs Proxy Protocol v2 or an application-layer token; and availability-zone coverage has to match, using AZ IDs since AZ names differ per account.

code

bash · 17 lines
bash
# Provider: expose the NLB as an endpoint service, gated by acceptance
SVC=$(aws ec2 create-vpc-endpoint-service-configuration \
  --network-load-balancer-arns "$NLB_ARN" \
  --acceptance-required \
  --query 'ServiceConfiguration.ServiceId' --output text)

aws ec2 modify-vpc-endpoint-service-permissions \
  --service-id "$SVC" \
  --add-allowed-principals arn:aws:iam::444455556666:root

# Consumer: create the interface endpoint in their own VPC
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0consumer \
  --vpc-endpoint-type Interface \
  --service-name com.amazonaws.vpce.eu-west-1.vpce-svc-0a1b2c3d \
  --subnet-ids subnet-0aaa subnet-0bbb \
  --security-group-ids sg-0client

go deeper

for a junior

Know that AWS PrivateLink lets one account expose a service privately to another, and that the consumer creates an interface endpoint in their own VPC to reach it.

for a middle

Describe the provider side concretely: a Network Load Balancer, a VPC endpoint service configuration, acceptance settings and an allowed-principals list, with consumers creating interface endpoints against the service name.

for a senior

Bring the operational detail — one endpoint service per load balancer, Proxy Protocol v2 to recover the consumer's endpoint id, AZ IDs rather than AZ names for zone coverage, and who pays for what on each side.

for a principal

Frame it as a trust-boundary decision. Argue when a one-way, single-door exposure beats routed connectivity, how many endpoint services a platform should have versus one multiplexed ingress, and how consumer onboarding, DNS ownership and cost allocation are governed at scale.

## The shape of the mechanism AWS PrivateLink has two sides. The consumer side is the familiar interface endpoint. The provider side is a **VPC endpoint service**: you register a Network Load Balancer (or a Gateway Load Balancer for inline appliances) as the service's front door, and AWS assigns a service name of the form `com.amazonaws.vpce.<region>.vpce-svc-<id>`. Consumers create an interface endpoint for that name, get ENIs with private IPs in their own subnets, and connect to those IPs. PrivateLink carries the traffic between the two VPCs without ever joining them into one routed network. The provider controls who may connect. `--acceptance-required` puts each new endpoint connection into a pending state until you approve it, and the allowed-principals list restricts which accounts, roles or organisations can even create an endpoint. Both are worth using: acceptance gives a human gate, the principal list keeps the service from being discoverable and connectable by everyone who learns the name. ```bash aws ec2 create-vpc-endpoint-service-configuration \ --network-load-balancer-arns arn:aws:elasticloadbalancing:eu-west-1:111122223333:loadbalancer/net/svc/abc \ --acceptance-required aws ec2 modify-vpc-endpoint-service-permissions \ --service-id vpce-svc-0a1b2c3d \ --add-allowed-principals arn:aws:iam::444455556666:root ``` ## Why a lead reaches for it The reason to choose this over other private connectivity is **isolation, not reachability**. PrivateLink exposes exactly one endpoint — the load balancer's listeners — and nothing else in the provider VPC. Traffic is unidirectional by construction: the consumer initiates, the provider cannot originate connections back. The two address spaces are never merged, so overlapping RFC 1918 ranges are a non-issue, and neither side has to coordinate CIDR allocations or route propagation with the other. For a service consumed by dozens of tenants or by another company, this is decisively better than routed connectivity, where every new consumer is another set of routes, another CIDR negotiation, and another network with broad access to yours. It also scales organisationally. Onboarding a consumer is an allow-list entry, not a network change, and offboarding is removing one. That is a governance property as much as a technical one. ## What you give up **Granularity and count.** An endpoint service fronts one NLB. Exposing many microservices either means many endpoint services — each with consumer endpoints to pay for and manage — or a single shared ingress behind the NLB that multiplexes by hostname or path at layer 7. Most mature platforms choose the latter and put a routing tier behind the NLB, accepting that the perimeter is now one door with application-level authorization behind it. **Layer 4 only, and cost.** The service must be TCP-fronted. Consumers pay endpoint-hours per AZ plus per-GB, and providers pay for the NLB and its processing, so a chatty, high-volume integration is materially more expensive than routed traffic. **Caller identity.** Targets behind the NLB see connections whose source is PrivateLink infrastructure, not the consumer's client address, so IP-based allow-lists behind the load balancer are meaningless. To recover provenance you enable **Proxy Protocol v2** on the target group, which prepends connection metadata including a custom field carrying the consumer's VPC endpoint id — but your application must parse it, and TLS termination points have to be arranged accordingly. For anything security-relevant, an application-layer credential such as mTLS or a signed token is the sounder answer, with the endpoint id used for attribution rather than authorization. **Availability zones.** A consumer can only connect from AZs where the endpoint service is available, and AZ *names* are randomised per account, so `eu-west-1a` in one account is not the same physical zone as in another. Coordinate on **AZ IDs**, and make sure the NLB has subnets in every zone consumers need — otherwise a consumer's endpoint in an uncovered zone simply cannot be created, or their traffic crosses zones with the latency and cost that implies. **DNS.** Consumers get endpoint-specific names by default. A provider can configure a private DNS name for the endpoint service — which requires proving domain ownership through a DNS TXT record — so consumers can use your real hostname; without that, every consumer wires up their own private hosted zone. ## The decision in one line Choose an endpoint service when the consumer is a different trust boundary — another team's account, another business unit, a customer — and you want to expose a single TCP front door with no shared network. Choose routed connectivity when the two sides are one trust domain that needs broad, bidirectional access, and accept the CIDR and route coordination that comes with it.

  • Your targets need the consumer's identity, but every connection appears to come from PrivateLink. What are the options?
    Enable Proxy Protocol v2 on the NLB target group, which prepends connection metadata including a field carrying the consumer's VPC endpoint id, and parse it in the application. For authorization rather than attribution, prefer an application-layer credential — mutual TLS or a signed token per consumer — since network provenance alone is a weak identity.
  • A consumer says they cannot create an endpoint in one of their Availability Zones. What do you check?
    Whether the endpoint service is available in that zone, which depends on the NLB having a subnet there. Compare using AZ IDs rather than AZ names, because names are randomised per account and eu-west-1a in their account may be a different physical zone than yours. Adding an NLB subnet in the missing zone resolves it.
  • When would you not use an endpoint service and use routed connectivity instead?
    When both sides are one trust domain needing broad, bidirectional access to many hosts and ports rather than one TCP front door — for example a shared services VPC that must both serve and initiate connections. Routed connectivity costs you CIDR coordination and a much wider blast radius, which is exactly what PrivateLink trades away.

saying these in an interview costs you the question

  • Says an Application Load Balancer fronts the endpoint service
  • Assumes the provider can initiate connections to consumers
  • Thinks overlapping CIDRs must still be resolved
  • Expects the consumer's client IP at the target
  • Ignores that AZ names differ between accounts

context