Most cost advice assumes the bill follows the work: use less, pay less. There is a set of AWS charges where that link is broken. You switch the thing off and the charge continues. Or you build the cheaper path, and traffic quietly keeps taking the expensive one.
These are hard to find because nothing breaks. No error, no alert, no failed health check. The only symptom is a number on an invoice that nobody can attribute.
1. CloudFront plans that bill while disabled
In November 2025 AWS introduced flat-rate pricing plans for CloudFront. Instead of per-request and per-GB rates, you subscribe one distribution to a plan and pay a flat monthly fee: $15 for Pro, $200 for Business, $1,000 for Premium.
Then this, straight from the AWS documentation:
You can disable a distribution that is subscribed to a pricing plan, but you will still incur charges for that plan.
Disabling a distribution does what you expect on the traffic side. AWS is explicit that CloudFront stops accepting traffic for that domain name. Requests go to zero. The monthly fee does not.
Deleting it is not the escape either:
You can't delete a distribution that is subscribed to a pricing plan.
The required order is cancel, then delete. You must first cancel the pricing plan, and once the plan is cancelled you can delete the distribution. Doing it the other way round leaves you paying a flat monthly fee for a distribution that serves nobody, and it can sit there for months because zero traffic generates zero signals.
The plan also locks your WAF in place
A flat-rate plan requires an AWS WAF web ACL in front of the distribution, and that association is not optional afterwards. AWS says the resource cannot be removed or disassociated from your distribution unless you switch to pay-as-you-go pricing for that distribution.
So the plan is not purely a billing choice. It pins part of your security configuration too, and unpinning it means changing pricing models.
The tier ladder is not what it looks like
This one is worth knowing before you pick a tier. Data transfer is 50 TB on Pro, Business and Premium alike. The only thing that moves as you climb is the request allowance: 10 million, 125 million, 500 million.
If you are upgrading from Pro to Business to get more bandwidth, you are paying $185 a month more for exactly the same 50 TB. More bandwidth is Premium-only, where allowances are configurable up to 600 TB. The 75 TB level moves the flat fee to $1,450 a month.
There are no overage charges past your allowance, which sounds generous until you read what happens instead: AWS might serve your traffic from fewer or more distant edge locations. You do not pay more, you get slower. For a CDN, that is the thing you were buying.
One more constraint: each pricing plan covers one CloudFront distribution with up to one apex domain. Multi-distribution estates multiply the fee.
2. Public IPv4: attached stopped meaning free
This one is old enough that most people know it and still have not acted on it, which is exactly why it is still worth money.
Before February 2024, an Elastic IP attached to a running instance carried no charge. Only idle ones cost you. That mental model, attached equals free, is still what a lot of engineers carry around, and it has been wrong since 1 February 2024.
AWS now charges for all public IPv4 addresses whether attached to a service or not, at $0.005 per hour. That is roughly $3.65 per address per month, and in-use and idle are priced identically. There is no longer a cheap state for a public IPv4 address.
Individually it is trivial. It stops being trivial when you count them: every NAT gateway, every public load balancer node, every bastion, every instance in a public subnet, across every account and every environment. Estates with a few hundred addresses are paying four figures a month for something that used to be free and still feels free.
3. The gateway endpoint that never took over
The standard advice for cutting NAT gateway cost is to add a gateway VPC endpoint for S3 and DynamoDB. It is good advice. AWS charges nothing to run one: there is no additional charge for using gateway endpoints.
The trap is that creating the endpoint does not guarantee traffic uses it, and when it does not, nothing tells you.
Longest prefix match beats your new route
VPC route selection uses longest prefix match. In AWS's words, they use the most specific route that matches the traffic to determine how to route it. A route specifying S3's exact IP address range in the same region takes precedence over the gateway endpoint route.
So if someone previously added specific S3 prefixes pointed at the NAT gateway, those routes keep winning after you create the endpoint. And here is why it never surfaces: the bypassed traffic still reaches S3 through the public service endpoint. Nothing errors. Nothing retries. Throughput is normal. AWS documents the behaviour plainly, that instances in subnets not associated with these route tables use the public service endpoint rather than the gateway endpoint.
Meanwhile NAT gateway data processing is charged for every GB regardless of source or destination, from $0.045 per GB in US regions. Worth noting that this is a separate charge from the NAT gateway hourly fee, which is confusingly also $0.045 in those regions, one per hour and one per GB.
Two more ways it silently does not apply
- Cross-region. A gateway endpoint covers S3 and DynamoDB in its own region only, because prefix lists are region-specific. A bucket or table in another region still exits through the NAT and pays per GB. Backup and replication jobs are the usual offenders here.
- Unselected route tables. The endpoint covers only the route tables you picked when you created it. Subnets outside that list keep reaching S3 over its public address and paying the NAT. Anything created after the endpoint, by a different team or a different Terraform module, tends to land here.
In all three cases the endpoint exists, the architecture diagram is correct, and the NAT bill barely moves.
4. Cross-AZ transfer, and the line item that names no service
Two ECS tasks talking in the same availability zone over private IPv4: free. The same call to a task in a neighbouring zone is $0.01 per GB leaving the sender and $0.01 per GB arriving at the receiver. AWS confirms the symmetry directly, applying an inter-zone data transfer charge of $0.01 per GB in each direction.
So $0.02 per GB round trip. At 25 TB a month crossing the boundary that is about $500. That is price-list arithmetic (25,000 GB x $0.02), not a scan result, and it holds under either GB convention.
The reason this is hard to act on is attribution. You get one regional data transfer line under EC2. It tells you the region. It does not tell you which service made the calls, which means the person reading the bill cannot hand it to the team that caused it.
The default that needs a redeploy
On 23 July 2026 AWS launched zone-aware routing for Amazon ECS Service Connect, which prefers endpoints in the same zone as the calling task. The announcement contains two statements that need reading together:
- Zone-aware routing is enabled by default for all new and existing services and requires no additional infrastructure or application code changes.
- Existing services require a one-time redeployment to enable the new routing behavior.
Both are in the same announcement. Read quickly, the first sentence says you are already covered. The second says you are not, until you redeploy. If you read only the first, you will assume this is handled and keep paying for it.
How much is at stake depends on your zone count. With three zones and round-robin endpoint selection, roughly two-thirds of Service Connect calls leave the caller's zone, since two of three candidate targets sit elsewhere. Zone-aware routing pulls most of them back, not all: traffic still redistributes across healthy AZs when local endpoints are unhealthy or below capacity thresholds, which is correct behaviour and worth the occasional cross-zone byte.
There is no alert for a service still running the old behaviour. The fix is a redeploy per service, and the only way to know which services need it is to go and look.
The common shape
Put the four side by side and the same structure shows up:
- The signal you would expect is absent. Zero traffic on a disabled distribution. No errors on bypassed endpoint routes. Normal throughput on cross-zone calls.
- The billing line does not name the cause. Regional data transfer under EC2. NAT data processing as one aggregate. A flat plan fee with no usage attached.
- Correct-looking configuration. The endpoint exists. The distribution is disabled. The architecture review passes.
Which means none of these get caught by watching for anomalies. There is no spike. The cost was always there, it just never went down when you expected it to. Anomaly detection finds changes; this category is defined by not changing.
What to check this week
- List CloudFront distributions with a flat-rate plan, then cross-reference against distributions with zero or near-zero requests. Cancel the plan before deleting anything.
- Count public IPv4 addresses across all accounts. Multiply by $3.65. Decide whether that number deserves an IPv6 or shared-NAT conversation.
- For every VPC with a gateway endpoint, check the route tables actually associated with it, and check for specific S3 prefix routes pointing at a NAT. Then check whether your S3 traffic is even in-region.
- List ECS services using Service Connect that have not been redeployed since 23 July 2026. Those are still paying cross-zone rates.
None of this is exotic. It is all documented behaviour working as designed. The cost sits in the gap between what the console shows you and what the invoice totals, and that gap does not close on its own.
Sources
Quotes are verbatim from AWS documentation. Monthly totals are my arithmetic on AWS's published rates and are labelled as such in the text.
- CloudFront flat-rate pricing plans
- Deleting a CloudFront distribution
- Amazon CloudFront pricing
- AWS announces flat-rate pricing plans (18 Nov 2025)
- Amazon VPC pricing (IPv4, NAT, data transfer)
- New AWS public IPv4 address charge
- VPC gateway endpoints and route precedence
- Optimizing data transfer costs with NLB (inter-zone charges)
- Zone-aware routing for ECS Service Connect (23 Jul 2026)
- Announcing zone-aware routing in ECS Service Connect