Skip to content
AWS aws networking 5 min read

VPC Endpoints & PrivateLink

By default, when a server inside your VPC (Virtual Private Cloud, your own private network in AWS) talks to an AWS service like S3 (Simple Storage Service, AWS object storage), the traffic leaves your VPC and travels over the public internet. That means you need an Internet Gateway or a NAT Gateway (Network Address Translation Gateway, which lets private servers reach the internet) — and a NAT Gateway charges you for every gigabyte of data. VPC endpoints let your VPC reach AWS services privately, keeping the traffic on Amazon’s internal network. This is safer (nothing touches the public internet) and often much cheaper.

There are two kinds of endpoint, and picking the right one matters for both cost and which services you can reach.

Gateway endpoints vs interface endpoints

These two endpoint types work very differently under the hood. A gateway endpoint adds a target to your route table so traffic to a service is redirected onto the AWS private network. An interface endpoint (powered by AWS PrivateLink) creates a network card inside your subnet with a private IP address that you send traffic to.

FeatureGateway endpointInterface endpoint (PrivateLink)
Supported servicesS3 and DynamoDB onlyMost AWS services (and partner/third-party services)
How it worksRoute table entryAn ENI (Elastic Network Interface, a virtual network card) with a private IP in your subnet
CostFree~$0.01 per hour per AZ + ~$0.01 per GB processed
Reachable fromInside the VPC only (and via route tables)Inside the VPC, and across peering/VPN/Direct Connect
Uses a private IP / DNSNo (route-based)Yes (private DNS name resolves to the ENI)

When to use a gateway endpoint: any time your VPC accesses S3 or DynamoDB. It is free and removes the need to route that traffic through a NAT Gateway.

When to use an interface endpoint: for every other service (for example SSM, Secrets Manager, ECR, CloudWatch, SQS, Kinesis) when you want fully private access with no internet path. Be aware it has an hourly cost, so create one only for the services you actually use.

Creating a gateway endpoint (S3)

A gateway endpoint attaches to one or more route tables. AWS automatically adds a route for the service’s prefix list (a managed list of the service’s IP ranges) so matching traffic is sent privately.

Console steps

  1. Open the VPC console and choose Endpoints in the left menu.
  2. Click Create endpoint.
  3. For Type, select AWS services.
  4. In the service search box, type s3 and pick the entry ending in .s3 with type Gateway.
  5. Choose your VPC (for example vpc-0a1b2c3d).
  6. Under Route tables, tick the route tables used by your private subnets.
  7. Leave the default Full access policy (or attach a tighter one) and click Create endpoint.

CLI equivalent

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0a1b2c3d \
  --vpc-endpoint-type Gateway \
  --service-name com.amazonaws.us-east-1.s3 \
  --route-table-ids rtb-0a1b2c3d rtb-0e5f6g7h

Output:

{
    "VpcEndpoint": {
        "VpcEndpointId": "vpce-0a1b2c3d4e5f6a7b8",
        "VpcEndpointType": "Gateway",
        "VpcId": "vpc-0a1b2c3d",
        "ServiceName": "com.amazonaws.us-east-1.s3",
        "State": "available",
        "RouteTableIds": [
            "rtb-0a1b2c3d",
            "rtb-0e5f6g7h"
        ]
    }
}

Cost gotcha: Gateway endpoints are completely free and they stop S3/DynamoDB traffic from going through a NAT Gateway. If your private subnets read or write a lot of S3 data through a NAT Gateway, you are paying NAT data-processing charges (around $0.045 per GB) for nothing. A few terabytes a month is hundreds of dollars wasted that a free gateway endpoint eliminates instantly.

An interface endpoint places an ENI with a private IP into each subnet you choose, and a security group controls who can reach it. With private DNS enabled, the normal service hostname (for example secretsmanager.us-east-1.amazonaws.com) automatically resolves to the private ENI, so you do not change any application code.

Console steps

  1. In the VPC console, go to Endpoints and click Create endpoint.
  2. For Type, select AWS services.
  3. Search for the service (for example secretsmanager) and pick the entry with type Interface.
  4. Choose your VPC vpc-0a1b2c3d.
  5. Under Subnets, select one subnet per Availability Zone you want covered (for example subnet-0a1b2c3d in us-east-1a, subnet-0e5f6g7h in us-east-1b).
  6. Pick a Security group that allows inbound HTTPS (TCP 443) from your application’s CIDR.
  7. Keep Enable DNS name checked, then click Create endpoint.

CLI equivalent

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0a1b2c3d \
  --vpc-endpoint-type Interface \
  --service-name com.amazonaws.us-east-1.secretsmanager \
  --subnet-ids subnet-0a1b2c3d subnet-0e5f6g7h \
  --security-group-ids sg-0a1b2c3d \
  --private-dns-enabled

Output:

{
    "VpcEndpoint": {
        "VpcEndpointId": "vpce-0c9d8e7f6a5b4c3d2",
        "VpcEndpointType": "Interface",
        "VpcId": "vpc-0a1b2c3d",
        "ServiceName": "com.amazonaws.us-east-1.secretsmanager",
        "State": "pending",
        "PrivateDnsEnabled": true,
        "NetworkInterfaceIds": [
            "eni-0a1b2c3d4e5f6a7b8"
        ]
    }
}

The endpoint moves from pending to available in a minute or two. After that, calls to Secrets Manager from your private subnets stay entirely inside AWS — no Internet Gateway or NAT Gateway needed.

Terraform example

Defining endpoints as code keeps them consistent across environments.

# Free gateway endpoint for S3
resource "aws_vpc_endpoint" "s3" {
  vpc_id            = "vpc-0a1b2c3d"
  service_name      = "com.amazonaws.us-east-1.s3"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = ["rtb-0a1b2c3d"]
}

# Interface endpoint for Secrets Manager
resource "aws_vpc_endpoint" "secretsmanager" {
  vpc_id              = "vpc-0a1b2c3d"
  service_name        = "com.amazonaws.us-east-1.secretsmanager"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = ["subnet-0a1b2c3d", "subnet-0e5f6g7h"]
  security_group_ids  = ["sg-0a1b2c3d"]
  private_dns_enabled = true
}

Best Practices

  • Always add a gateway endpoint for S3 and DynamoDB in any VPC that uses them — it is free and cuts NAT Gateway data charges.
  • Only create interface endpoints for services you actually use, since each one bills per hour per Availability Zone.
  • Spread interface endpoints across multiple Availability Zones so a single AZ failure does not break private access.
  • Lock down the interface endpoint security group to allow inbound 443 only from the CIDR ranges that need it.
  • Attach an endpoint policy to restrict which buckets, tables, or actions the endpoint allows — endpoints are a great place to enforce least privilege.
  • Keep private DNS enabled on interface endpoints so applications need no code changes.
Last updated June 15, 2026
Was this helpful?