AWS Cost Optimization: NAT Instances vs. NAT Gateways
A comparison of pricing structures for AWS NAT Instances and NAT Gateways - and how you can optimize costs for each.
9 min read
AWS supports both NAT Instances and NAT Gateways. Which one should you use? Let's look at some of the elements that might factor into your decision.
What is a NAT?
In simplest terms, a Network Address Translation (NAT) server is a compute instance that enables traffic between private subnets in a network and other networks.
The use of NATs has become prevalent on AWS with the company's emphasis on Virtual Private Clouds (VPCs). A VPC is a private IP address space that functions much like a standard physical network. In the past, you could create AWS resources by default in a public address space. But these days, many AWS features (such as Amazon EC2) can only be used in the context of a VPC.
And that's where NATs come into play. Let's say you're deploying a new VPC on AWS. At creation time, you can divide your VPC into subnets (logical groups of IP addresses).
Depending on how you define your networking routes, a subnet can be either public or private. A public subnet contains a route to an Internet gateway, enabling both inbound and outbound traffic from and to the public Internet. A private subnet only has routes that connect to other subnets in the network.
A private subnet is a great tool for enhancing the security of your Web applications. By hosting compute in a private subnet, you limit the potential attack surface area available to hackers. (For more details, see our documentation on how we configure networks for our customers at TinyStacks.)
However, very few compute jobs these days can work completely disconnected from other networks. Most need to integrate with one or more external services. A NAT serves as an outbound connection point to an Internet gateway. Network rules route traffic targeted to external IPs through the NAT, which acts as a router between the internal and external services.
Additionally, you may need to connect your network to other networks you own. These may be other VPCs you own hosting other application workloads or even your on-premise network.
Using VPC, you can build out a full virtual network consisting of public and private subnets. As part of this design, you can define one or more NATs for your private subnets.
NAT Instances vs. NAT Gateways: Basic differences
For many years, the only way to create a NAT was by creating a NAT instance. A NAT instance is a regular Amazon EC2 virtual machine that's configured to act as a router between internal and external networks.
NAT instances are relatively easy to set up. Indeed, AWS provides the precise steps in their docs. However, there are several downsides to creating your own NAT instance:
- You're responsible for maintaining it - e.g., for applying software patches to the OS, or replacing the instance if it goes down.
- The performance (throughput, etc.) is limited to the size of the EC2 instance you select. If outbound traffic from your private subnets increases dramatically for any reason, the NAT instance can become a chokepoint.
- A single NAT instance is a single point of failure in your application stack. Ideally, you would want to maintain a pool of instances if you need to ensure high availability. But that requires additional time to build and maintain. It also increases your overall costs.
To solve these problems. AWS added NAT Gateways as a feature to its ever-growing suite. A NAT Gateway is an AWS-managed service that essentially does what a NAT instance does. In other words, AWS maintains a scalable fleet of NAT instances on your behalf. This makes NAT Gateway a maintenance-free alternative to NAT instances that's guaranteed to scale with your traffic needs.
NAT Instances vs. NAT Gateways: Pricing
So you should always use a NAT Gateway, right? Well...not so fast. While a NAT Gateway is convenient, you pay a premium for that convenience.
With a NAT instance, you pay for the cost of the EC2 instance you are running. You also pay for any data you transfer between Availability Zones (e.g., to another EC2 instance running in a subnet in a different Availability Zone) or any data you transfer out to the Internet.
What's notable here is that you don't pay for inbound data. In other words, you can download terabytes of data from Internet sources and it won't cost you any extra.
By contrast, with NAT Gateways, you pay for the number of NAT Gateway instances you run and for all data - whether inbound or outbound. If you're downloading terabytes of data every month from another network, that cost can add up quickly.
You can see this difference clearly using the AWS Pricing Calculator. Assume you are running a back-end worker in a private subnet that downloads up to 1TB of data a month from somewhere on the Internet. If you use a t3.medium EC2 instance for your NAT instance, your cost in the us-east-1 region would come out to about $39 a month. But with NAT Gateway, that cost doubles to about $79 a month.
And mind you, that's using EC2 on-demand pricing. If you are confident that you current NAT instance sizes will fit your needs long-term, you can use reserved instances to reduce the cost even further. A one-year reserved reservation prepaid in full for a t3.medium instance type brings the monthly cost down to about $18. That's over half off the on-demand price.
NAT instances are also cheaper if you're transferring a lot of data between different VPCs. Say you have a VPC Peering connection from your VPC to another VPC in the same AWS region. Transferring an additional 5TB of data will cost you around only around USD $0.01, or $102.40/month. By contrast, the same data transfer using a NAT Gateway will run you $230.40/month - over twice as much.
However, a NAT instance isn't always cheaper. For outbound data out of your AWS region, NAT Gateways have a small edge. For a NAT instance, this will run you (at current rates) between USD $0.05 and $0.09 per GB. By contrast, a NAT Gateway charges a flat amount for all data regardless of destination (around USD $0.045).
This could make a difference if you primarily use your NAT for data export. However, the NAT instance pricing becomes cheaper the more data you transfer. So it likely won't make a significant difference for most applications.
The hidden data transfer cost: Data across availability zones
There's another sneaky, hidden cost with data transfer, too. And it can end up adding a lot to your monthly bill if you use a NAT Gateway or NAT instance.
AWS charges a fee - in the US, around USD $0.01 per GB - for data transfers across Availability Zones (AZ). This can bite you if you have a VPC with subnets in different AZs as part of a high availability design.
Say that you have a VPC in us-east-1 with three private subnets in three different AZs: us-east-1a, us-east-1b, and us-east-1c. You decide to create a single NAT device (either an EC2 instance or Gateway) in us-east-1a. You create a single NAT instance in us-east-1a to serve all three private subnets.
This means that, if you have processes in us-east-1b and us-east-1c that are processing data through the NAT, you're transferring data across AZs. That translates to an additional $100 or so a month for every 10TB of data you process. For teams processing terabytes or even petabytes of data, this can become a gargantuan additional cost.
NAT instances vs. NAT Gateways: Cost optimization
Supporting NATs adds increased costs to your application stack. No matter which solution you use, you'll pay for every EC2 NAT instance or NAT Gateway instance you enable and also for data transfer.
Of these, data transfer will likely be the largest pain point. If your app sends 10TB of data back to your on-premises network via a NAT, for example, that'll add over $900/month to your overall bill.
The first best practice - whether you're using NAT instances or NAT Gateways - is to understand how much data you're transferring in and out. You can set up Amazon CloudWatch metrics that will give you this information for free. For example, with NAT Gateways, you can easily monitor total bytes in and out.
With both NAT instances and Gateways, you can also limit the number of NAT instances or Gateways that you run. At a minimum, you will need one NAT instance or Gateway per connection point to another network.
The tradeoff here, as I discussed, is availability. If a NAT instance or a NAT Gateway goes down, that could impact your application's performance. You may be able to work around this by ensuring your application isn't dependent on NAT connectivity to run.
Here are some other ways you might limit costs for each technology.
Reducing AWS cost for NAT Gateways
Compared to NAT instances, NAT Gateways have a straightforward pricing model. You pay for each NAT instance and a flat rate for most data transfers. (Don't forget about that pesky cross-AZ transfer charge...)
Given this, the best way to minimize costs with NAT Gateways is to limit your overall data transfer. AWS themselves recommend seeing if you can re-architect your data transfers to prevent data from crossing availability zones.
For public Internet data transfers, you may want to move your data transfers out of a private subnet and into a public subnet. Traffic that flows through an Internet gateway accrues no additional charges. The trade-off is that you'll lose some of the security benefits from running within a private subnet. If you go this route, ensure that your network security policies on your public subnet are strictly configured to prevent attempted ingress from malicious actors.
Alternatively, you can also look into caching data and only requesting differential data wherever possible.
If you can't limit data transfers and your use case primarily involves ingesting data from other sources, consider using NAT instances, which provide unlimited data transfer in for free.
Optimizing AWS costs with NAT Instances
As we already discussed, the first - and best - way to make your NAT instances cheaper is to purchase reserved instances. Beyond that, you can minimize costs by being strategic with your data transfers.
As noted above, the largest data transfer costs with NAT instances accrue when you transfer data out of a region. To minimize this, consider if it's possible to keep the data within the region by storing it in another AWS service.
For example, if you're archiving data, consider storing it in an Amazon S3 bucket or in Amazon Glacier instead of transferring it to your on-premises hardware. If you're transferring data between VPCs in different regions, consider co-locating both services in the same region.
The TinyStacks approach to simplifying networking on AWS
Networking is notoriously one of the most confusing aspects of configuring infrastructure on AWS. That's why at TinyStacks, we aim to make networking easy.
Our end-to-end application stacks are optimized to provide the lowest possible AWS cost for all of our customers. We automatically configure NAT instances for your app's private subnets on your behalf. We also put all our NAT instances in auto-scaling groups so that your NAT never becomes a performance bottleneck.
The result? Application stacks that "just work", are secure by default, and save our customers an average 70% off their networking costs.
Try it out today and see the TinyStacks difference for yourself!