AWS PrivateLink: VPC Endpoints and Endpoint Services
A comprehensive guide to AWS PrivateLink: VPC Endpoints and Endpoint Services on AWS, covering core concepts, configuration, best practices, and real-world use cases..
20+ years shipping production infrastructure and CI/CD at scale. Lessons pulled from things that broke in production.
- ✓Basic understanding of AWS services and cloud computing concepts.
AWS PrivateLink: VPC Endpoints and Endpoint Services is like having a smart assistant that handles the heavy lifting so you don't have to manage servers yourself.
| Chrome | Firefox | Safari | Edge |
|---|---|---|---|
| ✓ | ✓ | ✓ | ✓ |
You’ve spent weeks hardening your security groups, locking down IAM policies, and encrypting everything in transit. Then someone decides to route traffic to an S3 bucket through a NAT gateway over the internet. That’s a security hole you can drive a truck through. AWS PrivateLink fixes this by keeping traffic entirely within the AWS network, never touching the public internet. It’s not just about security—it’s about operational simplicity and compliance. When you use PrivateLink, you eliminate the need for internet gateways, NAT devices, and firewall rules for inter-VPC or service access. But misconfiguring it can silently break your architecture. I’ve seen teams spend days debugging timeouts only to realize their endpoint policy was too restrictive. This article covers what PrivateLink is, how to set it up correctly, and the gotchas that will bite you in production.
Why PrivateLink? The Problem with VPC Peering and NAT
VPC peering and NAT gateways are common approaches for connecting services across VPCs, but they come with significant operational baggage. VPC peering requires transitive routing hacks, non-overlapping CIDRs, and manual route table updates that break under scale. NAT gateways introduce a single point of failure and egress costs that spiral as traffic grows. Worse, neither provides granular access control — once traffic leaves your VPC, you lose visibility into which consumer is talking to which service. PrivateLink solves this by exposing services via Elastic Network Interfaces (ENIs) inside consumer VPCs, eliminating the need for internet gateways, NAT devices, or peering connections. Traffic stays within the AWS backbone, and IAM policies can enforce per-consumer access. This is not just a networking improvement; it's a security boundary shift. You stop trusting the network and start trusting identity.
Anatomy of a VPC Endpoint: Interface vs Gateway Endpoints
AWS offers two types of VPC endpoints: Interface endpoints (powered by PrivateLink) and Gateway endpoints (for S3 and DynamoDB). Interface endpoints create an Elastic Network Interface (ENI) in your subnet with a private IP, allowing traffic to reach supported AWS services or your own endpoint services. Gateway endpoints are a route table entry that directs traffic to S3 or DynamoDB without leaving the AWS network, but they only work for those two services and cannot be used for custom services. For PrivateLink, you always use Interface endpoints. The key difference: Interface endpoints cost $0.01 per AZ per hour plus data processing charges, while Gateway endpoints are free but limited. In practice, use Gateway endpoints for S3/DynamoDB to save costs, and Interface endpoints for everything else. Never mix them — a common mistake is trying to use a Gateway endpoint for a custom service, which silently fails.
Building an Endpoint Service: The Provider Side
To expose your application via PrivateLink, you create a Network Load Balancer (NLB) in your service VPC, then register it as an endpoint service. The NLB must be internal (no public IP) and in the same VPC as your application instances. The endpoint service is defined by a service name (e.g., com.amazonaws.vpce.us-east-1.vpce-svc-0example) and a set of allowed principals (AWS accounts or IAM roles). You can also configure acceptance required: if true, consumers must request access and you approve each connection. In production, always require acceptance to prevent unauthorized access. The NLB handles health checks and load balancing, so your application must be stateless behind it. Once the endpoint service is live, consumers can create VPC endpoints pointing to your service name. The ENIs in their VPC will route traffic to your NLB, which forwards to your application.
Consumer Side: Creating a VPC Endpoint
As a consumer, you create a VPC endpoint of type Interface in your VPC, specifying the service name provided by the producer. You must select subnets (one per AZ) where ENIs will be created. Each ENI gets a private IP from your subnet range. You also attach a security group that controls inbound traffic to the endpoint — this is your first line of defense. Optionally, enable private DNS so that DNS queries for the service's endpoint (e.g., my-service.example.com) resolve to the private IPs of the ENIs. Without private DNS, you must manually manage DNS or use Route 53 private hosted zones. In production, always enable private DNS to avoid brittle DNS workarounds. After creation, the endpoint state is 'pendingAcceptance' until the producer approves it. Once accepted, traffic flows.
Security: IAM Policies and Security Groups
PrivateLink security operates at two levels: network and identity. Network security is enforced by security groups attached to the VPC endpoint ENI. These control inbound traffic from the consumer's VPC to the endpoint. Identity security is enforced by IAM policies on the endpoint service that restrict which principals (AWS accounts, IAM roles, or users) can create endpoints to your service. Additionally, you can use AWS PrivateLink endpoint policies (for AWS services) to control what actions consumers can perform. For custom services, the NLB security group controls traffic from the endpoint ENIs to your application. In production, use a combination: security groups to restrict source IPs (if known), and IAM to restrict accounts. Never rely solely on security groups — they don't prevent a malicious account from creating an endpoint if the service allows all principals.
DNS and Private Hosted Zones: Making It Work
PrivateLink endpoints support private DNS names. When you enable private DNS on a VPC endpoint, AWS automatically creates a Route 53 private hosted zone for the service's DNS name (e.g., my-service.example.com) and associates it with your VPC. This zone contains A records pointing to the ENI private IPs. For custom endpoint services, you must configure a private DNS name on the service side and verify domain ownership. Without private DNS, consumers must either use the endpoint-specific DNS name (which includes the VPC endpoint ID) or create their own Route 53 records. In production, always use private DNS — it's free and eliminates DNS management overhead. However, be aware that private DNS only works within the VPC; if you need cross-region or on-premises resolution, you'll need Route 53 Resolver endpoints or conditional forwarding.
Monitoring and Troubleshooting PrivateLink
Monitor PrivateLink using VPC Flow Logs, CloudWatch metrics, and endpoint service events. Key metrics: ActiveConnections, NewConnections, PacketsIn/Out, and BytesProcessed. For endpoint services, track the number of endpoints and their states. Common issues: endpoint stuck in 'pendingAcceptance' (producer hasn't approved), security group blocking traffic, or NLB health checks failing. Use VPC Flow Logs to see if traffic reaches the ENI. If you see 'REJECT' in flow logs, check security groups. If traffic reaches the ENI but not the application, check NLB target group health. Another frequent issue: cross-account DNS resolution fails if the consumer's VPC doesn't have the private hosted zone associated. In production, set up CloudWatch alarms on ActiveConnections dropping to zero — that indicates a connectivity failure.
Cost Optimization: Data Processing and Cross-AZ Charges
PrivateLink costs include: hourly charges per endpoint per AZ ($0.01/hr), data processing charges ($0.01/GB for data processed by the endpoint), and cross-AZ data transfer costs if the consumer and producer are in different AZs. To optimize: use one endpoint per AZ and ensure consumers in the same AZ connect to the endpoint in that AZ (use private DNS which returns AZ-local IPs). Avoid creating endpoints in every AZ if you only need one. Also, minimize data transfer by co-locating consumer and producer in the same region and same AZ if possible. For high-throughput workloads, consider using Gateway endpoints for S3/DynamoDB to avoid data processing charges. In production, we saved 30% by consolidating endpoints and using AZ affinity.
Scaling PrivateLink: Multi-AZ and Multi-Region
For high availability, create VPC endpoints in at least two AZs. The NLB backing the endpoint service must also be multi-AZ. PrivateLink does not natively support cross-region; endpoints are region-specific. To connect across regions, use VPC peering or Transit Gateway between the consumer VPC and a proxy VPC that hosts the endpoint, or use AWS PrivateLink with inter-region VPC peering (which adds complexity). Alternatively, expose the service via a global accelerator. In production, we use a hub-and-spoke model: a central VPC hosts the endpoint service, and consumer VPCs in the same region connect via PrivateLink. For cross-region, we replicate the service or use a VPN. Never rely on a single AZ — an AZ outage will take down your connectivity.
Real-World Failure Modes and Mitigations
PrivateLink failures often stem from misconfiguration. Common failure modes: (1) Security group on the endpoint ENI blocks traffic — always verify with flow logs. (2) NLB target group health checks fail — ensure your application responds to health checks on the correct port and path. (3) Endpoint service acceptance required but producer never approves — set up automation to auto-approve trusted accounts. (4) Private DNS not enabled — leads to DNS resolution failures. (5) Cross-account IAM policies missing — consumers get 'AccessDenied' when creating endpoints. Mitigations: use AWS Config rules to enforce private DNS enabled, security group rules, and acceptance required. Set up CloudWatch alarms on endpoint state changes. In production, we also use a Lambda function that auto-approves endpoints from known accounts and sends alerts for unknown ones.
Alternatives to PrivateLink: When Not to Use It
PrivateLink is not always the best choice. For high-throughput, low-latency workloads within the same VPC, use direct VPC connectivity. For S3 and DynamoDB, use Gateway endpoints (free). For on-premises connectivity, use Direct Connect or VPN. If you need transitive routing across many VPCs, Transit Gateway is simpler than a mesh of PrivateLink endpoints. PrivateLink also has a limit of 1000 endpoints per VPC (soft limit, can be increased). If you exceed that, consider using Transit Gateway or VPC peering. In production, we use a decision matrix: same VPC? Direct connect. Same region, different VPC? PrivateLink. Cross-region? Transit Gateway or VPN. On-premises? Direct Connect. Never force PrivateLink where simpler solutions exist.
Production Checklist: Deploying PrivateLink Safely
Before deploying PrivateLink in production, verify: (1) NLB is internal and multi-AZ with healthy targets. (2) Endpoint service requires acceptance and has IAM policy restricting principals. (3) Consumer VPC endpoints have private DNS enabled and security groups allowing traffic from application subnets. (4) Flow logs are enabled on both sides. (5) CloudWatch alarms on endpoint state and active connections. (6) DNS resolution works end-to-end (test with nslookup). (7) Cross-account IAM roles are correctly set up. (8) Cost estimates are within budget. (9) Have a rollback plan: if PrivateLink fails, can you fall back to a direct connection or VPN? In production, we always deploy a parallel VPN connection as a backup during the initial migration. Once stable, we remove the backup.
| File | Command / Code | Purpose |
|---|---|---|
| create-vpc-endpoint.sh | aws ec2 create-vpc-endpoint \ | Why PrivateLink? The Problem with VPC Peering and NAT |
| describe-endpoint-types.sh | aws ec2 describe-vpc-endpoint-services \ | Anatomy of a VPC Endpoint |
| create-endpoint-service.sh | aws ec2 create-vpc-endpoint-service-configuration \ | Building an Endpoint Service |
| create-consumer-endpoint.sh | aws ec2 create-vpc-endpoint \ | Consumer Side |
| endpoint-service-policy.json | { | Security |
| verify-private-dns.sh | nslookup my-service.example.com | DNS and Private Hosted Zones |
| check-endpoint-state.sh | aws ec2 describe-vpc-endpoints \ | Monitoring and Troubleshooting PrivateLink |
| create-multi-az-endpoint.sh | aws ec2 create-vpc-endpoint \ | Scaling PrivateLink |
| auto-approve-endpoint.py | ec2 = boto3.client('ec2') | Real-World Failure Modes and Mitigations |
| check-endpoint-limits.sh | aws ec2 describe-vpc-endpoints \ | Alternatives to PrivateLink |
| test-connectivity.sh | curl -v https://my-service.example.com/health | Production Checklist |
Key takeaways
Common mistakes to avoid
2 patternsOverlooking aws privatelink vpc endpoints basic configuration
Ignoring cost implications
Interview Questions on This Topic
What is AWS PrivateLink: VPC Endpoints and Endpoint Services and when would you use it?
Frequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Lessons pulled from things that broke in production.
That's AWS. Mark it forged?
6 min read · try the examples if you haven't