Every cloud security architecture starts with the same question: how do I connect to a service without going over the public internet? The answer is almost always PrivateLink + private DNS. But most engineers treat this as a checkbox — “enable PrivateLink, done.” This article explains what actually happens at the network and DNS level.
The Problem: Public Endpoints#
By default, when your application connects to a cloud service (a database, an API, a SaaS platform), the traffic flow looks like this:
┌──────────────────────┐ PUBLIC INTERNET ┌──────────────────────┐
│ Your VPC │ │ Service Provider │
│ │ │ │
│ ┌──────────┐ │ ┌─────────────────────────┐ │ ┌──────────┐ │
│ │ App │───────┼───▶│ Internet Gateway │───┼──▶│ Service │ │
│ │ Server │ │ │ Public IP routing │ │ │ Endpoint │ │
│ └──────────┘ │ │ Anyone can reach this │ │ └──────────┘ │
│ │ └─────────────────────────┘ │ │
└──────────────────────┘ └──────────────────────┘Problems with this:
- Traffic traverses the public internet — potentially inspectable, interceptable
- The service endpoint has a public IP — visible to anyone, attackable
- Your VPC needs an Internet Gateway or NAT — broader attack surface
- Compliance frameworks (DORA, NIS2, PCI-DSS) may prohibit public internet paths for sensitive data
What PrivateLink Does#
PrivateLink creates a private, one-way connection between your VPC and a service provider’s VPC — without either side exposing anything to the public internet.
┌──────────────────────┐ ┌──────────────────────┐
│ Your VPC │ AWS Backbone (private) │ Provider VPC │
│ │ │ │
│ ┌──────────┐ │ ┌─────────────────────────┐ │ ┌──────────┐ │
│ │ App │───────┼───▶│ VPC Endpoint (ENI) │ │ │ Service │ │
│ │ Server │ │ │ 10.0.1.47 │────┼──▶│ (NLB) │ │
│ └──────────┘ │ │ Private IP in YOUR VPC │ │ └──────────┘ │
│ │ └─────────────────────────┘ │ │
└──────────────────────┘ └──────────────────────┘
No Internet Gateway
No public IP
No NAT requiredHow It Works Step by Step#
- Service provider creates a VPC Endpoint Service backed by a Network Load Balancer (NLB)
- You create a VPC Interface Endpoint in your VPC, specifying the service
- AWS provisions an Elastic Network Interface (ENI) in your subnet with a private IP from your CIDR
- Traffic from your app → the ENI → AWS internal backbone → provider’s NLB → their service
- The connection is unidirectional — the provider cannot initiate connections back into your VPC
Key insight: the endpoint gets an IP address from your own VPC’s subnet. From your application’s perspective, the service looks like it’s running inside your network.
Interface Endpoint vs Gateway Endpoint#
AWS has two types:
| Interface Endpoint (PrivateLink) | Gateway Endpoint | |
|---|---|---|
| Mechanism | ENI with private IP in your subnet | Route table entry |
| Services | Almost everything (400+ services, third-party SaaS) | S3 and DynamoDB only |
| Cost | Per-hour + per-GB data processing | Free |
| DNS | Private DNS zones | Prefix lists in route tables |
| Cross-region | No (same region) | No (same region) |
For this article, we focus on Interface Endpoints — they’re what people mean when they say “PrivateLink.”
The DNS Layer: Making It Transparent#
Creating a PrivateLink endpoint gives you a private IP. But your application connects to service.example.com, not 10.0.1.47. How does the DNS hostname resolve to the private endpoint instead of the public IP?
This is where Private DNS comes in.
Without Private DNS#
Your App Public DNS (Route 53)
│ │
│ "What is the IP of │
│ analytics.snowflake.com?" │
│──────────────────────────────────▶│
│ │
│ "52.xx.xx.xx" (public IP) │
│◀──────────────────────────────────│
│ │
│ Connect to 52.xx.xx.xx │
│ ──── goes over the internet ──▶ │Even with PrivateLink configured, your app still resolves the public IP and bypasses the endpoint entirely.
With Private DNS Enabled#
When you enable Private DNS on an Interface Endpoint, AWS automatically:
- Creates a Private Hosted Zone (PHZ) for the service’s domain
- Associates the PHZ with your VPC
- Adds DNS records pointing the service hostname to your endpoint’s private IPs
Your App Private Hosted Zone (in your VPC)
│ │
│ "What is the IP of │
│ analytics.snowflake.com?" │
│──────────────────────────────────▶│
│ │
│ "10.0.1.47" (private endpoint) │ ← PHZ intercepts before public DNS
│◀──────────────────────────────────│
│ │
│ Connect to 10.0.1.47 │
│ ──── stays inside AWS ─────────▶ │The application code doesn’t change. Same hostname, same port, same TLS certificate. But the traffic now flows privately.
How DNS Resolution Order Works#
When an instance in your VPC makes a DNS query, the resolution order is:
1. VPC DNS Resolver (AmazonProvidedDNS at VPC CIDR + 2)
│
├── Check Private Hosted Zones associated with this VPC
│ └── Match found? → Return private IP (done)
│
├── Check Route 53 Resolver Rules (forwarding rules)
│ └── Rule matches? → Forward to on-prem DNS / custom resolver
│
└── No match? → Forward to public DNS
└── Return public IPThe Private Hosted Zone always wins over public DNS for any domain it covers. This is how PrivateLink transparently redirects traffic without application changes.
The Full Picture: PrivateLink + DNS Together#
Let’s trace a complete request from application to service:
┌─────────────────────────────────────────────────────────────────────────────┐
│ Your VPC (10.0.0.0/16) │
│ │
│ ┌──────────┐ ① DNS Query ┌──────────────────────────────┐ │
│ │ │──────────────────────────▶│ VPC DNS Resolver │ │
│ │ App │ │ (10.0.0.2) │ │
│ │ Server │ ② Response: 10.0.1.47 │ │ │
│ │ │◀──────────────────────────│ Checks Private Hosted Zone │ │
│ │ 10.0.0.5│ │ → finds endpoint IP │ │
│ └────┬─────┘ └──────────────────────────────┘ │
│ │ │
│ │ ③ TCP connect to 10.0.1.47 │
│ │ │
│ ┌────▼──────────────────────────┐ │
│ │ VPC Interface Endpoint (ENI) │ │
│ │ 10.0.1.47 │ │
│ │ Subnet: 10.0.1.0/24 │ │
│ └────────────┬──────────────────┘ │
│ │ │
└───────────────┼──────────────────────────────────────────────────────────────┘
│
│ ④ AWS internal backbone (never touches the internet)
│
┌───────────────┼──────────────────────────────────────────────────────────────┐
│ Provider VPC │ │
│ ┌────────────▼──────────────────┐ ┌─────────────────┐ │
│ │ Network Load Balancer │────▶│ Service │ │
│ │ (Endpoint Service) │ │ (your data) │ │
│ └───────────────────────────────┘ └─────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘Steps:
- App queries DNS for
service.example.com - VPC resolver checks the Private Hosted Zone → returns
10.0.1.47 - App connects to
10.0.1.47— a local ENI in the same subnet - Traffic flows over AWS backbone to the provider’s NLB
Zero public internet exposure. The app, the endpoint, and the DNS resolution all stay private.
Cross-Account and Cross-Region Patterns#
Cross-Account (Same Region)#
PrivateLink works natively across AWS accounts in the same region. The provider shares the endpoint service name (e.g., com.amazonaws.vpce.eu-west-1.vpce-svc-abc123), and you create an endpoint in your account.
Cross-Region#
PrivateLink does not work across regions directly. Common patterns:
Pattern 1: Inter-Region VPC Peering + PrivateLink
Region A (your app) ──peering──▶ Region B (endpoint) ──PrivateLink──▶ ProviderPattern 2: Transit Gateway + PrivateLink
Region A ──TGW peering──▶ Region B ──PrivateLink──▶ ProviderPattern 3: Provider offers regional endpoints Most major services (Snowflake, Databricks, etc.) deploy endpoint services in each region, so you connect locally.
On-Premises Connectivity#
For hybrid environments, the pattern extends to on-premises:
On-Premises AWS VPC Provider
┌──────────┐ ┌────────────────┐ ┌──────────┐
│ App │──Direct Connect──│ Route 53 │ │ │
│ Server │ or VPN │ Resolver │ │ Service │
│ │ │ Inbound │ │ │
│ │──DNS query──────▶│ Endpoint │ │ │
│ │◀─private IP──────│ │ │ │
│ │ │ │ │ │
│ │──traffic────────▶│ VPC Endpoint───┼──PrivateLink─│ │
└──────────┘ └────────────────┘ └──────────┘You need a Route 53 Resolver Inbound Endpoint so your on-premises DNS can forward queries to the VPC resolver, which then returns the private endpoint IPs.
Azure Private Link and GCP Private Service Connect#
The same concepts exist on other clouds:
| Concept | AWS | Azure | GCP |
|---|---|---|---|
| Private endpoint | VPC Interface Endpoint | Private Endpoint | Private Service Connect Endpoint |
| Service exposure | Endpoint Service + NLB | Private Link Service + Standard LB | Service Attachment |
| DNS integration | Private Hosted Zone | Private DNS Zone | Cloud DNS |
| Cross-region | No (use peering) | Yes (Global Private Access) | Yes (Global access option) |
Azure and GCP both support cross-region private connectivity natively — AWS requires peering or Transit Gateway.
Security Considerations#
1. Endpoint Policies#
VPC Endpoint Policies control which principals can use the endpoint and which resources they can access. Without a policy, anyone in the VPC can use the endpoint to access any resource in the target service.
{
"Statement": [
{
"Principal": {"AWS": "arn:aws:iam::123456789012:role/AppRole"},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*",
"Effect": "Allow"
}
]
}2. Security Groups on Endpoints#
Interface Endpoints have security groups. Lock them down:
- Allow inbound only from your application subnets
- Allow only the required ports (443 for HTTPS, etc.)
3. DNS Leakage#
If Private DNS isn’t configured correctly, DNS queries may fall through to public DNS, and traffic will bypass the endpoint. Monitor with VPC Flow Logs and DNS query logging.
4. Data Exfiltration via Endpoints#
An overly permissive endpoint policy could allow an attacker to exfiltrate data to an external account’s resources. Use endpoint policies + S3 bucket policies + SCPs to restrict cross-account access.
Cost#
PrivateLink isn’t free:
| Component | Cost (us-east-1, approximate) |
|---|---|
| Interface Endpoint | |
| Data processed | ~$0.01/GB |
| Cross-AZ data transfer | Standard rates apply |
For a typical deployment across 2 AZs: ~$15/month + data processing fees. Often negligible compared to the security and compliance value.
When to Use PrivateLink#
| Use Case | PrivateLink? |
|---|---|
| Connecting to SaaS (Snowflake, Databricks, etc.) from a regulated VPC | Yes |
| Internal microservices across accounts | Yes |
| Public-facing API consumed by external customers | No (use API Gateway) |
| S3 access from VPC | Use Gateway Endpoint (free) |
| Compliance requires no public internet paths | Yes |
| Cost-sensitive dev/test environments | Maybe not (public endpoint + TLS is usually fine) |
Related Articles#
- Governing AI Inference in the Data Cloud — how PrivateLink fits into a broader security architecture for AI workloads
- Data Sovereignty: Querying On-Prem Iceberg from Snowflake — using SSH tunnels as an alternative private connectivity pattern
- Query Your On-Premise DataLake Through a Private Tunnel — another approach to hybrid connectivity
