Skip to main content

Reaching Cloud Services Privately - Endpoints and PrivateLink

TL;DR
  • A cloud service such as S3 or SQS lives on public IPs by default. To reach it from a private subnet without a NAT gateway or an internet gateway, give the service a private path into your VPC.
  • AWS has two kinds. A gateway endpoint (S3 and DynamoDB only) is a route-table entry pointing a prefix list at the endpoint. It is free. An interface endpoint (PrivateLink) is an ENI with a private IP in your subnet plus a DNS override. It is billed per hour and per GB.
  • With an interface endpoint the work is done by DNS: the service's normal name resolves to the ENI's private IP. Turn private DNS off and the name resolves to the public IP, so traffic goes the old way.
  • PrivateLink is not peering. It exposes one service, one way (consumer to provider), and it works with overlapping CIDRs. The endpoint is also not the service: IAM and resource policies still apply.
  • GCP calls the pieces Private Google Access and Private Service Connect. Azure calls them service endpoints and Private Endpoint (Private Link).

Mental model​

ANALOGYEveryday

A company mailroom needs to send documents to the bank across town. Option one: a courier walks out the front door, crosses the street and enters the bank's public lobby. Option two: the company and the bank agree on a sealed internal tube that ends in a slot in the mailroom wall. Staff post the envelope in the slot and never go outside. A gateway endpoint is like adding a line to the mailroom's directory: "anything for the bank, use the tube". An interface endpoint is a slot installed in your own wall with its own label, so the name "Bank" now points at the slot instead of the lobby.

Where it breaks: the tube gets your envelope to the bank's front desk, nothing more. The bank still checks who sent it and what it is allowed to do. The endpoint is a path, not a permission.

ANALOGYFor engineers

It is a local proxy address for a remote dependency. Instead of calling sqs.us-east-1.amazonaws.com at some public address, your code (unchanged) reaches a private IP that forwards to the same API. Like service discovery, the trick is that the name stays the same and the answer changes. A gateway endpoint is the routing flavour of this trick (a more specific route wins, see routing in a VPC). An interface endpoint is the DNS flavour.

Where it breaks: a sidecar is yours to configure and secure. An endpoint is a managed object that carries its own security group and its own endpoint policy, and a wrong one fails with a timeout or AccessDenied, not a clean connection error.

How it works​

Start from the problem. A private subnet has no route to an internet gateway (cloud network model, routing in a VPC). Its instances can still reach public AWS services if a NAT gateway forwards them, but then every byte is billed as NAT data processing and every request leaves via a public IP. Endpoints remove that hop.

Three paths to the same service​

private subnetEC2 10.0.11.20NAT gateway + IGWRoute table rowInterface endpoint ENIAWS serviceS3, SQS ...per-GB NAT feeS3 prefix list to vpce-110.0.11.77, hour + GBpublic IP, via IGWprefix list route, freeprivate IP in your subnetVPC 10.0.0.0/16
Solid line: out through the NAT gateway and internet gateway. Dashed line: a route-table entry sends the S3 prefix list to a gateway endpoint. Dotted line: an interface endpoint ENI inside the subnet receives the traffic. The second and third paths never touch a public IP.

Gateway endpoints: a route, not a device​

A gateway endpoint exists only for S3 and DynamoDB. When you create one you pick the route tables to associate with it, and AWS adds a route whose destination is a managed prefix list (a named set of the service's public CIDRs) and whose target is the endpoint, vpce-... (AWS gateway endpoints). Because that prefix list is more specific than 0.0.0.0/0, longest-prefix match sends S3-bound packets to the endpoint and everything else to the NAT gateway, as in routing in a VPC.

Nothing about the name changes. s3.us-east-1.amazonaws.com still resolves to public IPs; the route table recognises those IPs as members of the S3 prefix list and diverts them. There is no ENI, no security group, and no charge for the endpoint or the data it carries (AWS PrivateLink pricing, as of 2026-10).

Interface endpoints: an ENI plus a DNS answer​

An interface endpoint creates an elastic network interface with a private IP in each subnet you choose (one per AZ) and attaches a security group to it (AWS interface endpoints). Reaching the ENI is just in-VPC traffic covered by the local route. What makes applications use it is private DNS: when enabled, AWS associates a hidden private hosted zone with your VPC so the service's regular name resolves to the ENI addresses.

Before and after, as dig would show it (addresses are illustrative; the public answers change from query to query):

dig +short sqs.us-east-1.amazonaws.com # private DNS off, or no endpoint
(several public addresses owned by AWS)
dig +short sqs.us-east-1.amazonaws.com # interface endpoint, private DNS on
10.0.11.77
10.0.12.81

One private IP per endpoint ENI, so a three-AZ endpoint returns three. Private DNS only works if the VPC has both enableDnsSupport and enableDnsHostnames set to true (AWS interface endpoints).

The VPC resolver and where private DNS lives​

Every instance asks the Amazon-provided DNS resolver, reachable at 169.254.169.253 and at the VPC base address plus 2 (10.0.0.2 for a 10.0.0.0/16 VPC) (AWS DNS in your VPC). It answers from private hosted zones associated with the VPC first and falls back to public DNS. That is split-horizon DNS: the same name gives different answers depending on who asks. Recursion and record types are explained in DNS and DNS records and routing; here the point is only that the resolver can lie to you, on purpose, inside the VPC.

Cross-cloud map​

ConceptAWSGCPAzureGotcha
Route-level private path to storageGateway endpoint (S3, DynamoDB), prefix list routePrivate Google Access, enabled per subnet; traffic goes to Google public IPs but stays on Google's networkService endpoint, enabled per subnet; adds a VNet identity to the service firewallThe service keeps its public IP in all three, and none of these gives the service a private IP
Private IP for a service in your networkInterface endpoint (ENI, PrivateLink)Private Service Connect endpoint (internal IP you choose, forwarding rule)Private Endpoint (NIC with a private IP, Private Link)Each costs money and each needs DNS to be correct
Publish your own service privatelyEndpoint service (NLB or GWLB behind it)Private Service Connect service attachment (behind an internal load balancer)Private Link service (behind a Standard Load Balancer)One-way, consumer to provider. Overlapping CIDRs are fine
Private DNS for the abovePrivate hosted zone, hidden one with private DNS onCloud DNS private zone, such as googleapis.com pointed at the VIPPrivate DNS zone such as privatelink.blob.core.windows.netLink the zone to the VPC or VNet or the name stays public
Hybrid DNSRoute 53 Resolver inbound and outbound endpointsCloud DNS forwarding and peeringAzure DNS Private ResolverOn-premises resolvers need an explicit forwarder

For GCP the product view (Private Google Access in the exam context) is on the gcp-ace DNS, NAT and IPs page. This page keeps the vendor-neutral idea.

Choosing an endpoint type​

TypeMechanismServicesCost (AWS)Reachable from on-prem
Gateway endpointRoute table entry, prefix list to vpceS3 and DynamoDB onlyFreeNo, the route lives in the VPC route table only
Interface endpointENI per AZ, security group, private DNSMost AWS APIs, partner and your own endpoint services, and S3 as wellPer hour per AZ plus per GBYes, over VPN or Direct Connect, if DNS resolves to the ENI

Reading it: S3 has both kinds. Use the gateway endpoint inside the VPC because it is free; use an S3 interface endpoint when on-premises or a peered network must reach S3 privately (the gateway endpoint docs list the limits on reaching them from outside the VPC).

A worked cost comparison​

Unit prices as of 2026-10 for us-east-1, quoted from the PrivateLink pricing and VPC pricing pages (check them, prices and regions differ): NAT gateway $0.045 per hour and $0.045 per GB processed; interface endpoint $0.01 per hour per AZ and $0.01 per GB for the first tier of data; gateway endpoint $0.

Take a private subnet that moves 1,000 GB a month to S3 and needs the NAT gateway for other traffic anyway:

PathHourly partPer-GB partMonthly total
Via NAT gateway (S3 traffic only)Already paid for other traffic1,000 x $0.045 = $45.00$45.00 extra
Via S3 gateway endpoint$0$0$0.00
Via an interface endpoint, 3 AZs3 x 730 h x $0.01 = $21.901,000 x $0.01 = $10.00$31.90

(730 is the usual hours-per-month approximation: 8,760 hours in a year divided by 12.) The gateway endpoint wins for S3 and DynamoDB whenever the traffic goes through NAT today. An interface endpoint pays for itself only when the per-GB saving beats the fixed hourly cost: at these prices the break-even is where 21.90 + 0.01 x GB = 0.045 x GB, so about 626 GB a month. Cross-AZ data transfer adds on top if the instance and the ENI are in different AZs.

Deep dive​

Endpoint policies and locking a bucket to your VPC​

An endpoint carries an endpoint policy, an IAM-style resource policy that limits which principals and actions may use that endpoint. The default allows everything (AWS endpoint policies). It is an extra filter, evaluated together with the caller's IAM policy and the service's own resource policy; all must allow.

The other direction is a bucket policy that denies any request that did not come through your endpoint, using the aws:SourceVpce condition key (S3 bucket policy examples). Together they give "the bucket is reachable only from this VPC, and the VPC can reach only these buckets". The sharp edge is that the deny also blocks you, from a laptop or the console, which is why teams keep a break-glass role excluded from the condition.

To publish an internal service to another VPC or account, put it behind a Network Load Balancer (or Gateway Load Balancer), create an endpoint service on it, and let consumers create an interface endpoint to it (PrivateLink concepts). Properties worth stating:

  • One-way. Connections are initiated from the consumer's ENI to the provider's NLB. The provider cannot open connections into the consumer VPC.
  • No network merge. Consumers see one IP and one port, not your subnets. CIDRs may overlap, which peering forbids, so this is the standard answer when two companies both used 10.0.0.0/16.
  • Per-AZ. The consumer gets one ENI per chosen subnet; keep the endpoint in the same AZs as the clients so traffic does not cross AZs.
clientendpoint ENINLBendpoint servicetargetsPrivateLink, consumer to providerno route back into the consumer VPCConsumer VPC 10.0.0.0/16Provider VPC 10.0.0.0/1610.0.11.77
The consumer VPC holds the endpoint ENI and initiates every connection. The provider VPC holds the NLB and the service. Both VPCs use the same CIDR on purpose: nothing is routed between them, so the overlap does not matter.

DNS resolution order and hybrid DNS​

Inside the VPC the resolver checks, roughly, private hosted zones associated with the VPC, then forwarding rules, then public DNS (AWS DNS in your VPC). A private hosted zone only answers for VPCs it is associated with; forgetting the association is the usual reason "the private name resolves in one VPC but not the other".

On-premises machines cannot query 169.254.169.253 or the base-plus-2 address from outside the VPC. For hybrid setups, Route 53 Resolver provides an inbound endpoint (on-premises resolvers forward AWS-hosted names to ENIs in your VPC) and an outbound endpoint with forwarding rules (instances forward corporate names to on-premises resolvers) (Route 53 Resolver). Forward the same zone both ways and you create a loop, so each zone is forwarded in exactly one direction.

GCP: Private Google Access versus Private Service Connect​

Private Google Access lets VMs with only internal IPs reach Google APIs. It is switched on per subnet, and traffic still goes to Google public IPs, over Google's network (Private Google Access). The special names private.googleapis.com (199.36.153.8/30) and restricted.googleapis.com (199.36.153.4/30) resolve to fixed virtual IP ranges that are only routable from inside, so you can reach them from on-premises over a hybrid link (configure Private Google Access).

Private Service Connect (PSC) is the PrivateLink analogue: a consumer endpoint is an internal IP address in your VPC (backed by a forwarding rule) that targets either Google APIs or a producer's service attachment (Private Service Connect). Choose Private Google Access for "my private VMs call Google APIs"; choose PSC when you want a stable IP you control, per-endpoint policy, or a third-party producer.

Azure: service endpoint versus private endpoint​

A service endpoint extends your subnet's identity to a service such as Storage. The service firewall can then allow that subnet, but the service keeps its public IP and traffic is still addressed to it (service endpoints overview). A private endpoint is a network interface with a private IP in your subnet mapped to one specific resource, and DNS is changed so the resource name resolves to it, typically through a privatelink. private DNS zone (Private Endpoint overview, Private Endpoint DNS). The private endpoint is the Azure analogue of an AWS interface endpoint, and the service endpoint is closer to AWS gateway endpoints or GCP Private Google Access.

Textbook vs real world​

The textbook saysProduction doesWhy
Cloud services live on the public internet, so a private host needs NAT or a proxy to reach themPrivate subnets reach S3, SQS and SaaS over endpoints, often with no internet gateway in the VPC at allProviders expose service front ends on private IPs and routes, which cuts the NAT bill and the exposure
DNS gives one global answer per nameThe VPC resolver gives a different answer for the same name inside the VPC (split-horizon)It is how an endpoint redirects traffic without changing application code
To reach a service in another network, peer the networksExpose just that service with PrivateLink, Private Service Connect or Private LinkPeering merges routing domains and forbids overlapping CIDRs. An endpoint exposes one service, one way
Private means unauthenticatedEndpoints keep IAM, resource policies and security groups in forceA network path is not an authorization decision

In production​

  • SaaS vendors sell private connectivity. Snowflake documents AWS PrivateLink for its accounts, Datadog documents sending telemetry over PrivateLink, and MongoDB Atlas documents private endpoints. Each publishes an endpoint service that you consume with an interface endpoint in your VPC.
  • Compliance-driven "no internet gateway" VPCs. Workloads with no internet route reach AWS APIs only through endpoints, and endpoint policies plus aws:SourceVpce bucket policies make the allowed destinations explicit.
  • Private Kubernetes clusters. AWS documents the endpoints a cluster with no internet access needs, including ECR, S3 and CloudWatch Logs (Amazon EKS private clusters). Image pulls are the usual high-volume item, which is why the gateway endpoint for S3 matters.
  • The NAT bill. The first thing to check on a surprising NAT line item is how much of it is S3 or DynamoDB traffic; the cost table above shows what moving it to a gateway endpoint saves.

History and evolution​

HISTORY
  • 2015 Private subnets reach S3 only through NAT or a public IP. AWS adds the S3 gateway endpoint, a route-table-based private path.
  • 2017 Route entries cannot cover most AWS APIs, which have no stable IP range suited to a prefix list. AWS PrivateLink introduces interface endpoints, an ENI plus DNS override, and DynamoDB gains a gateway endpoint.
  • 2018 ISVs want to serve customers without peering or shared CIDRs. Endpoint services behind an NLB make provider-side publication a normal pattern.
  • Around 2019 to 2021 Other clouds follow with the same ENI-plus-DNS idea: Azure Private Link and Private Endpoint, and Google Private Service Connect.
  • Now Private-by-default service access is a baseline for regulated workloads. Check each provider's service list for current coverage rather than a frozen figure.
  • Next More services offer private front ends directly, and gateway-style endpoints are joined by interface equivalents (S3 already has both).

The years above are from memory of the provider announcements; confirm them in each provider's release notes before quoting them in an interview.

Hands-on​

Create both endpoint types with the AWS CLI. The IDs are placeholders:

aws ec2 create-vpc-endpoint --vpc-id vpc-0abc --vpc-endpoint-type Gateway \
--service-name com.amazonaws.us-east-1.s3 --route-table-ids rtb-0abc
 
aws ec2 create-vpc-endpoint --vpc-id vpc-0abc --vpc-endpoint-type Interface \
--service-name com.amazonaws.us-east-1.sqs --subnet-ids subnet-0a subnet-0b \
--security-group-ids sg-0abc --private-dns-enabled

See which public ranges the gateway route represents, and ask the VPC resolver directly:

aws ec2 describe-prefix-lists --filters Name=prefix-list-name,Values=com.amazonaws.us-east-1.s3
PrefixLists:
- PrefixListId: pl-xxxxxxxx
PrefixListName: com.amazonaws.us-east-1.s3
Cidrs: [ ... AWS-owned ranges ... ]
nslookup sqs.us-east-1.amazonaws.com 169.254.169.253
curl -sv https://sqs.us-east-1.amazonaws.com 2>&1 | grep -E "Connected to|HTTP/"
Connected to sqs.us-east-1.amazonaws.com (10.0.11.77) port 443

Look for the connected-to address: a 10.x address means the endpoint path, a public address means private DNS is off or the endpoint is missing. A curl that hangs on connect points at the endpoint's security group missing inbound 443 from your subnet. For a gateway endpoint, check the route instead: aws ec2 describe-route-tables should show a DestinationPrefixListId row with a vpce- target. dig and nslookup exist on macOS and Linux. Output above is abbreviated and the addresses are examples.

Gotchas​

GOTCHAS5
A gateway endpoint works from on-premises
Turning private DNS off still works
The endpoint is up but connections time out
PrivateLink is VPC peering with extra steps
The endpoint policy replaces my IAM policy

Interview questions​

INTERVIEWHow does an EC2 instance in a private subnet reach S3 without a NAT gateway?mid
Show answer

Create an S3 gateway endpoint and associate it with the subnet's route table. AWS adds a route sending the S3 prefix list to the endpoint, which wins over the default route by longest-prefix match. It needs no ENI, no security group and costs nothing.

Follow-ups:

  • Gateway versus interface endpoint? Gateway is a free route, VPC-only, S3 and DynamoDB. Interface is an ENI with private DNS, billed per hour and GB, and reachable from on-premises.
  • Cost? The gateway endpoint is free. NAT would bill about $0.045 per GB for the same traffic (us-east-1, as of 2026-10).
INTERVIEWYou created an endpoint but traffic still goes through NAT. Why?mid
Show answer

Work out which kind it is. For a gateway endpoint, the route table of that subnet probably is not associated with the endpoint, so the prefix-list route is missing. For an interface endpoint, private DNS is likely off or the VPC lacks enableDnsSupport and enableDnsHostnames, so the name still resolves to a public IP.

Follow-ups:

  • How do you prove the path? dig the service name from the instance: a private IP means the interface endpoint. For a gateway endpoint, inspect the route table for the vpce- row and the VPC flow logs for the destination.
  • Why would a non-AWS client still go public? Its resolver never sees your private zone.
INTERVIEWExpose an internal service to a customer's VPC without sharing networks.senior
Show answer

Put the service behind an NLB, create an endpoint service on it, and let the customer create an interface endpoint to it, optionally with manual acceptance. The customer sees one private IP, you see connections from their endpoint, and neither network is routed into the other.

Follow-ups:

  • Consumer-side cost? They pay the hourly per-AZ endpoint fee and the per-GB charge.
  • AZ alignment? Enable the endpoint service in the AZs the consumers use, so traffic does not cross AZs.
INTERVIEWOn-premises must resolve names from a private hosted zone. How?senior
Show answer

Create a Route 53 Resolver inbound endpoint in the VPC and configure the on-premises DNS servers to forward that zone to its ENI addresses over VPN or Direct Connect. For the reverse direction, add an outbound endpoint and a forwarding rule to your corporate resolvers.

Follow-ups:

  • Loops? Forward each zone in one direction only, or queries bounce between resolvers.
  • Why not query the base-plus-2 resolver directly? It is only reachable from inside the VPC.
INTERVIEWMake a bucket reachable only from your VPC.senior
Show answer

Use a bucket policy that denies requests unless aws:SourceVpce equals your endpoint ID, and add an endpoint policy that limits which buckets and actions the endpoint allows. Requests then must come through the endpoint and the endpoint cannot reach other buckets.

Follow-ups:

  • Break-glass? Exclude a specific admin role from the deny, or you lock yourself out of the console.
  • Why SourceVpce rather than a source IP? Through an endpoint the source is a private address, so conditions on public IPs do not apply.
INTERVIEWWhat is split-horizon DNS and why does the cloud use it?junior
Show answer

It means the same name gets different answers depending on where the question comes from. The VPC resolver answers sqs.us-east-1.amazonaws.com with a private endpoint IP inside the VPC, while the internet gets the public one. It lets endpoints redirect traffic without changing application code. See DNS.

Follow-ups:

  • Where does the private answer come from? A private hosted zone associated with the VPC.
  • What breaks it? A VPC without the association, or without enableDnsSupport.

Fun facts​

FACTSTrivia worth knowing
  • Gateway endpoints cost nothing, and only S3 and DynamoDB support the gateway type.
  • S3 is unusual in having both a gateway and an interface endpoint.
  • The AWS resolver is reachable at two addresses, 169.254.169.253 and the VPC base plus 2.
  • Google's private.googleapis.com name resolves to 199.36.153.8/30, a fixed range that only works from inside a Google Cloud VPC or a connected network.

Cheat sheet​

DECISIONWhich private path?
  • S3 or DynamoDB, inside the VPC: gateway endpoint (free).
  • Any other AWS API, a SaaS vendor, your own service, or access from on-premises: interface endpoint (PrivateLink).
  • GCP: Private Google Access for Google APIs, or Private Service Connect when you need a controlled IP.
  • Azure: private endpoint when you need a private IP, service endpoint for a cheap subnet allow-list.