Skip to content

NAT Gateway

NAT Gateways provide outbound internet access for private-subnet instances. Shared-services uses HA (2 NAT Gateways) for critical services; dev uses a single NAT to save $32/month.


Strategy by Environment

Environment NAT Gateways Monthly Base Cost Rationale
Shared-Services 2 (HA — one per AZ) ~$64 Authentik SSO, Ansible, GitLab are all mission-critical; AZ failure must not interrupt them
Dev 1 (Single, us-west-2a) ~$32 Dev workloads tolerate temporary outages; saves $384/year
Production (future) 2-3 (HA) ~$64-96 Same rationale as shared-services

How NAT Gateway Works

Private subnet instances have no public IP. Their outbound internet traffic routes to the NAT Gateway, which translates the source IP to its Elastic IP (EIP) before forwarding to the Internet Gateway.

Private EC2 (10.1.35.46)
  → Route: 0.0.0.0/0 → NAT Gateway (us-west-2a)
  → NAT translates: 10.1.35.46 → EIP (public IP)
  → Internet Gateway → Internet

Data subnets (10.0.3-4.x, 10.1.20-21.x) have no default route — they cannot reach the internet at all.


HA NAT (Shared-Services)

Two NAT Gateways, one per AZ:

AZ NAT Gateway Location Serves
us-west-2a 10.0.1.0/24 (public subnet) All private subnets in us-west-2a
us-west-2b 10.0.2.0/24 (public subnet) All private subnets in us-west-2b

AZ failure behavior: If us-west-2a fails, us-west-2b continues uninterrupted. Traffic from us-west-2b stays within its AZ (no cross-AZ charges).

Monthly cost: ~$64 base + ~$20 data transfer ≈ ~$84/month


Single NAT (Dev)

One NAT Gateway in us-west-2a. All private subnets in both AZs route through it:

Private subnet us-west-2a → NAT in us-west-2a (local)
Private subnet us-west-2b → NAT in us-west-2a (cross-AZ charge applies)

AZ failure behavior: If us-west-2a fails, ALL private subnets lose internet access until a new NAT Gateway is deployed in us-west-2b and route tables are updated.

Monthly cost: ~$32 base + ~$10 data transfer ≈ ~$42/month


Upgrading Dev to HA NAT

If a dev AZ failure causes an unacceptable outage, upgrade to HA:

# environments/dev/variables.tf
variable "single_nat_gateway" {
  default = false  # was true
}
cd terraform-plan/organization/environments/dev
terraform plan   # Shows: +1 NAT Gateway, updated route tables
terraform apply  # Zero downtime — adds second NAT without disrupting existing one

Cost Details

NAT Gateway pricing (us-west-2): - Hourly: $0.045/hour × 730 hours = $32.85/month per NAT Gateway - Data processing: $0.045/GB processed

VPC Endpoints save NAT cost:

S3 and DynamoDB traffic bypasses the NAT Gateway via free gateway endpoints:

Without endpoint: EC2 → NAT Gateway ($0.045/GB) → Internet Gateway → S3
With endpoint:    EC2 → S3 Gateway Endpoint (FREE) → S3

Both VPCs have S3 and DynamoDB gateway endpoints configured.


Monitoring NAT Gateway

Key CloudWatch metrics to watch:

Metric Alert Threshold Action
BytesOutToDestination > 100 GB/hour Investigate unexpected egress
ErrorPortAllocation > 0 Port exhaustion — add another NAT Gateway
PacketsDropCount > 1,000 Check NAT Gateway health

NAT Gateway has a limit of ~55,000 concurrent connections. If exceeded, deploy a second NAT Gateway in the same AZ and split traffic.