NAT Gateway vs NAT Instance vs VPC Endpoint: Which One, and What It Costs

A NAT gateway is managed, highly available within its availability zone, and charges both per hour and per gigabyte processed. A NAT instance is an EC2 instance you run yourself — cheaper at low volume, your problem when it fails. A VPC endpoint is not a NAT replacement at all: it is a way to take specific AWS-service traffic out of the NAT path entirely, and for S3 and DynamoDB it costs nothing.

For most workloads the right answer is a NAT gateway plus gateway endpoints for S3 and DynamoDB. The interesting question is which interface endpoints are worth adding on top, and that depends on volume.

The three options

NAT gateway NAT instance VPC endpoint
What it does Outbound to anywhere Outbound to anywhere Reaches one AWS service privately
Managed by AWS You AWS
Availability Redundant within one AZ Single instance unless you build failover Redundant
Bandwidth Scales to 100 Gbps Limited by instance type Service-dependent
Hourly charge Yes, per gateway EC2 instance cost Free for gateway endpoints; hourly per AZ for interface endpoints
Per-GB charge Yes No (normal data transfer only) Free for gateway endpoints; per-GB for interface endpoints
Security groups Cannot be attached Can be attached Interface endpoints can
Port forwarding / bastion No Yes No

Where the money goes

A NAT gateway bills twice, and the second charge is the one that grows:

  • Hourly, per gateway. Three gateways for three-AZ redundancy triples it.
  • Per gigabyte processed, on everything passing through — in both directions.

That per-GB charge applies regardless of destination. Traffic from a private subnet to S3 in the same region is metered by the NAT gateway exactly like traffic to the public internet, even though it never leaves the AWS network. For a workload that pulls container images, ships logs, or reads datasets from S3, that is frequently the largest line on the VPC bill, and it is entirely avoidable.

Use the NAT gateway cost calculator to put your own numbers in; the arithmetic below is what it implements.

Gateway endpoints: free, and usually missing

S3 and DynamoDB are served by gateway endpoints, which work by adding a prefix-list route to your route tables. They have no hourly charge and no per-GB charge. None. The traffic simply stops traversing the NAT gateway.

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0123456789abcdef0 \
  --service-name com.amazonaws.eu-west-1.s3 \
  --route-table-ids rtb-0aaa111bbb222ccc3 rtb-0ddd444eee555fff6

That is the entire change. Every byte of S3 traffic from subnets using those route tables leaves the NAT meter immediately.

If you take one thing from this page: check whether your VPCs have an S3 gateway endpoint. A large share do not, and for any workload touching S3 it is free money.

Two things to watch. The route is added to specific route tables, so subnets whose route table you did not list keep using NAT. And an endpoint policy defaults to full access — worth tightening to the buckets that subnet should reach, which is a security improvement the NAT path cannot offer at all.

Interface endpoints: useful, but they have a fixed cost

Everything other than S3 and DynamoDB — ECR, CloudWatch Logs, SSM, Secrets Manager, KMS, STS, SQS, and a long list besides — uses interface endpoints, built on PrivateLink. Each places an ENI in each subnet you enable and charges per hour per availability zone plus per gigabyte.

Because the hourly charge is fixed, an interface endpoint only pays for itself above a volume threshold. Below it you are paying for idle ENIs.

The break-even, per endpoint:

monthly hourly cost = endpoints × AZs × hourly rate × 730
NAT saving          = GB diverted × (NAT per-GB − endpoint per-GB)

With NAT at $0.045/GB and interface endpoints at $0.01/GB, each diverted gigabyte saves $0.035. A three-AZ endpoint at $0.01 per AZ-hour costs about $22/month, so it needs roughly 625 GB/month through it to break even.

That number sorts the decision cleanly:

  • ECR — container image pulls are large and constant on any cluster that scales. Almost always worth it. Note that ECR needs three endpoints working together: ecr.api, ecr.dkr, and an S3 gateway endpoint for the layers themselves, which live in S3. Adding the first two without the third leaves the actual image data on the NAT path, which is the part with the volume.
  • CloudWatch Logs — high volume on anything chatty. Usually worth it.
  • SSM (ssm, ssmmessages, ec2messages) — low volume, but these let you run Session Manager on instances with no NAT at all, which can remove the NAT gateway entirely for a management-only subnet.
  • Secrets Manager, KMS, STS — tiny volume. Add them for the security posture, not the savings.

One subtlety cuts in your favour here: since 1 April 2022, inter-AZ data transfer to a VPC interface endpoint is free. Reaching an endpoint ENI in another availability zone costs nothing extra, so you are not forced to enable an endpoint in every zone purely to dodge a transfer charge. Enabling it per-AZ is still worth doing for latency and for surviving a zone failure, but it is a resilience decision rather than a billing one. Note that the exemption covers interface endpoints only — not Gateway Load Balancer endpoints.

When a NAT instance still makes sense

NAT instances are widely treated as legacy, and for production they mostly are. But two cases hold up:

Small, cost-sensitive environments. A t4g.nano running as a NAT instance costs a few dollars a month and has no per-GB charge — data transfer is billed as normal EC2 traffic. For a development VPC pushing a few hundred gigabytes, that is dramatically cheaper than a NAT gateway. AWS publishes a NAT instance AMI for exactly this.

When you need something a NAT gateway cannot do. A NAT instance is an EC2 instance: you can attach a security group to it, port-forward through it, run a proxy or a filtering rule set on it, log at the packet level, or use it as a bastion at the same time.

The costs are real. It is a single point of failure unless you build failover yourself, its bandwidth is capped by the instance type, it needs source/dest check disabled, and it needs patching. For anything carrying production traffic, the managed gateway is worth its price.

The order to do things in

  1. Add gateway endpoints for S3 and DynamoDB. Free, one route table change, immediate saving. Confirm every relevant route table is listed.
  2. Look at what the NAT gateway is actually carrying. VPC flow logs, filtered to the NAT ENI, grouped by destination. Guessing at this stage is how people add endpoints that never pay for themselves.
  3. Add interface endpoints above the break-even. ECR and CloudWatch Logs first, on the evidence from step 2.
  4. Consolidate gateways only if you accept the trade. One NAT gateway serving three AZs saves two hourly charges but introduces cross-AZ data charges and an availability-zone dependency for two of your three zones. For production, keep one per AZ.
  5. Consider dropping NAT entirely for subnets that only need AWS services. With the right endpoints in place, some workloads need no route to the internet at all — which is both cheaper and a materially better security position.