VPC Endpoints
By default, when a resource inside a VPC needs to communicate with an AWS service (such as S3, SSM, STS, CloudWatch), traffic goes out through the internet via a NAT Gateway or Internet Gateway. A VPC Endpoint is a resource that enables this communication privately, without traffic leaving the AWS network.
Why Use VPC Endpointsβ
There are three main motivations:
- Environments without internet access: Private subnets that don't have a NAT Gateway cannot reach AWS services through the public path. VPC Endpoints are the only form of communication in these cases.
- Security and compliance: In regulated environments, it's common to require that traffic never passes through the public internet, even if it's encrypted. VPC Endpoints ensure that communication stays within the AWS backbone.
- Cost: Traffic passing through a NAT Gateway has a per-GB processing cost. VPC Endpoints (especially Gateway Endpoints) eliminate this cost for high-volume services like S3 and DynamoDB.
Types of VPC Endpointsβ
AWS offers two types of endpoints, with different operating mechanisms:
Interface Endpoint (PrivateLink)β
The Interface Endpoint creates an ENI (Elastic Network Interface) inside your subnet with a private IP. When the resource makes a call to the AWS service, traffic is directed to this ENI instead of going out through the internet.
Characteristics:
- Creates an ENI with a private IP in the chosen subnet.
- Supports most AWS services (SSM, STS, CloudWatch, ECR, Secrets Manager, KMS, etc.).
- Can be protected with security groups (you control which resources can access the endpoint).
- Supports private DNS: when enabled, calls to the service's public endpoint (e.g.,
ssm.us-east-1.amazonaws.com) are automatically resolved to the ENI's private IP, without needing to change code or client configuration. - Has a cost: charged per hour of operation (~$0.01/hour per AZ) + cost per GB processed.
CLI creation example:
# Create Interface Endpoint for SSM
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0abc123 \
--service-name com.amazonaws.us-east-1.ssm \
--vpc-endpoint-type Interface \
--subnet-ids subnet-0def456 \
--security-group-ids sg-0ghi789 \
--private-dns-enabled
Gateway Endpointβ
The Gateway Endpoint works differently β it adds a route to the route table of the subnet that directs traffic to the AWS service through the internal backbone, without creating ENIs.
Characteristics:
- Works via route table β doesn't create ENIs or private IPs.
- Available only for S3 and DynamoDB.
- No additional cost β no hourly or traffic charges.
- Doesn't support security groups (control is done via endpoint policy and route tables).
- Doesn't need private DNS (routing is transparent).
CLI creation example:
# Create Gateway Endpoint for S3
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0abc123 \
--service-name com.amazonaws.us-east-1.s3 \
--vpc-endpoint-type Gateway \
--route-table-ids rtb-0jkl012
Comparisonβ
| Aspect | Interface Endpoint (PrivateLink) | Gateway Endpoint |
|---|---|---|
| Mechanism | ENI with private IP in subnet | Route in route table |
| Supported services | Most AWS services | S3 and DynamoDB only |
| Cost | ~$0.01/hour per AZ + GB processed | Free |
| Security groups | Yes | No |
| Private DNS | Yes (optional) | Not needed |
| Access control | Security groups + endpoint policy | Endpoint policy + route table |
For S3, AWS offers both types. The Gateway Endpoint is free and sufficient in most cases. Use the Interface Endpoint for S3 only if you need to access S3 from on-premise networks via VPN/Direct Connect (the Gateway Endpoint only works within the VPC).
How AWS Implements This Under the Hoodβ
The difference between the two endpoint types is not just functional β they are fundamentally different at the infrastructure layer.
The Interface Endpoint is powered by Hyperplane, an internal distributed platform at AWS that also drives the NAT Gateway, Network Load Balancer, and Transit Gateway. When you create an Interface Endpoint, AWS provisions an ENI in your subnet using the Nitro System (AWS's hypervisor with dedicated chips for network I/O). This ENI receives a real private IP in your subnet. Traffic arriving at this ENI is forwarded by Hyperplane nodes distributed across AZs that function as internal proxies to the target AWS service, all through AWS's private backbone. In simple terms: the Interface Endpoint is an AWS-managed network proxy that lives inside your VPC.
The Gateway Endpoint is simpler β it doesn't create any new physical component. It operates purely at the VPC's SDN (Software Defined Networking) layer. When you create a Gateway Endpoint, AWS modifies the mapping service (the system that translates virtual VPC IPs to physical locations) and adds a route to the route table pointing the service prefix to the internal backbone. Traffic is intercepted by the VPC's virtual router and redirected without intermediary β no ENI, no proxy. This is why the Gateway Endpoint is free: it doesn't consume additional resources, it's just a routing rule.
Private DNSβ
One of the most important aspects of the Interface Endpoint is private DNS. When enabled, it makes the service's public name (e.g., ssm.us-east-1.amazonaws.com) resolve to the endpoint ENI's private IP inside the VPC.
This means no changes are needed in clients β the AWS SDK, CLI, and any tool using the service's default hostname automatically start using the private endpoint.
Without private DNS:
ssm.us-east-1.amazonaws.com β 52.94.x.x (public IP, internet)
With private DNS enabled:
ssm.us-east-1.amazonaws.com β 10.0.1.47 (private IP, endpoint ENI)
Private DNS requires the VPC to have enableDnsSupport and enableDnsHostnames enabled. These settings are default in new VPCs, but it's worth verifying in older VPCs.
Endpoint Policyβ
Both Interface and Gateway Endpoints support endpoint policies, which is a JSON document in IAM policy format that controls which actions and resources can be accessed through the endpoint. This works as an additional security layer.
For example, to restrict an S3 Gateway Endpoint to only a specific bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-private-bucket/*"
}
]
}
This policy prevents any resource in the subnet from using the endpoint to access other buckets β an important protection against data exfiltration (an attacker with EC2 access cannot copy data to an external bucket through this endpoint).
The endpoint policy is an additional restriction that does not replace the resource's IAM permissions. Access is only allowed if both permit it: the resource/user's IAM policy AND the endpoint policy.
Practical Example: SSM without Internetβ
The most common VPC Endpoints scenario is enabling SSM Session Manager on instances that have no internet access. For this, three Interface Endpoints are required:
| Endpoint | Service Name | Function |
|---|---|---|
| SSM | com.amazonaws.<region>.ssm | Main Systems Manager API |
| SSM Messages | com.amazonaws.<region>.ssmmessages | Interactive session communication channel |
| EC2 Messages | com.amazonaws.<region>.ec2messages | Command channel for SSM Agent |
All three must be in the same VPC and accessible by the subnets where EC2 instances run. The endpoints' security group must allow inbound traffic on port 443 (HTTPS) from the instances.
If the instance also needs S3 access (for example, for SSM to write session logs), add a Gateway Endpoint for S3 β it's free and just needs to be associated with the subnet's route table.
Costsβ
Cost is an important factor in the decision to use VPC Endpoints:
| Type | Cost per hour (per AZ) | Cost per GB | Note |
|---|---|---|---|
| Gateway Endpoint | Free | Free | S3 and DynamoDB only |
| Interface Endpoint | ~$0.01/hour | ~$0.01/GB | Varies by region |
| NAT Gateway | ~$0.045/hour | ~$0.045/GB | For comparison |
For high-traffic volume services (such as frequent S3 access), the Gateway Endpoint is the best option as it's free. For services like SSM, STS, or KMS where traffic volume is low, the Interface Endpoint cost is minimal and generally lower than maintaining a NAT Gateway.
The math is simple: if you already need a NAT Gateway for other purposes, AWS service traffic will pass through it anyway. VPC Endpoints make more economic sense when you can completely eliminate the NAT Gateway or when traffic volume to a specific service is high enough to justify the dedicated endpoint.
A best practice recommended by AWS for organizations using AWS Organizations is to have a separate network account (Network Account). In this account, connectivity resources are centralized β Transit Gateway, shared VPCs (via AWS RAM), NAT Gateways, and VPC Endpoints themselves. This prevents each Organization account from creating its own endpoints and NAT Gateways, reducing costs and simplifying management. The decision of where to place VPC Endpoints changes significantly when a centralized network account exists, but this is a multi-account architecture topic that deserves a dedicated article.