The AWS charge nobody notices: Elastic IPs you stopped using
An Elastic IP costs $0.005 per hour — about $3.65 a month — whether or not it is attached to anything. Since 1 February 2024 AWS charges for ALL public IPv4 addresses, in-use ones included, so the old advice to 'just attach it' no longer avoids the charge. Find idle ones with: aws ec2 describe-addresses --query 'Addresses[?AssociationId==null]'. Releasing one is instant and free, but you cannot get the same address back.
This is the least interesting item on any cost report and one of the most common. It is worth five minutes because the fix is genuinely a one-liner, and because most of the advice written about it is now wrong.
What does an Elastic IP actually cost?
$0.005 per hour. That is $3.65 in a 30-day month, or roughly $44 a year, per address.
One is a rounding error. The reason it shows up on almost every account we look at is that they accumulate: a load balancer replaced, a NAT gateway migrated, a bastion host retired during a migration nobody finished. Each leaves an address behind, and nothing ever tells you.
On one account we found eight of them. $29.20 a month for nothing at all — not a large number, but it had been running for over a year, and every one of them pointed at infrastructure that no longer existed.
The advice you will find elsewhere is out of date
Search this and you will get a lot of pages saying "AWS only charges for Elastic IPs that are not attached to a running instance, so attach it or release it."
That was true until 1 February 2024. Since then AWS charges $0.005/hour for every public IPv4 address, whether it is attached to a running instance or not. The in-use exemption is gone.
Two consequences worth internalising:
- Attaching an idle EIP no longer avoids the charge. If the old advice is what stopped you releasing one, that reasoning has expired.
- Your public IPv4 bill is now a line item worth reading, not just the idle ones. Every load balancer, NAT gateway and public instance carries the cost.
If you have not looked at this since early 2024, the number is larger than you remember.
How do I find idle Elastic IPs?
One command, no tooling:
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].{ip:PublicIp,alloc:AllocationId,name:Tags[?Key==`Name`].Value|[0]}' \
--output table
AssociationId == null is the whole test: the address is allocated to you and
attached to nothing.
Across every region, since Elastic IPs are regional and forgotten ones love to hide in a region you set up once and never revisited:
for r in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
n=$(aws ec2 describe-addresses --region "$r" \
--query 'length(Addresses[?AssociationId==null])' --output text 2>/dev/null)
[ "$n" != "0" ] && [ -n "$n" ] && echo "$r: $n idle"
done
That loop is worth running even if you are confident. us-east-1 is rarely the
surprise; eu-west-1 from a launch three years ago usually is.
What does it cost me to fix?
aws ec2 release-address --allocation-id eipalloc-0123456789abcdef0
Instant, free, and it stops the meter immediately.
One thing to be careful about: you cannot get the same address back. Once released it returns to the AWS pool and someone else may take it within minutes. Before releasing, check whether the address is:
- In a DNS record anywhere — including a customer's DNS you do not control. This is the one that bites. If a partner allowlisted your IP or pointed a record at it, releasing it breaks them silently and you find out days later.
- In a firewall allowlist — yours or a third party's.
- In a payment provider or API allowlist. Several require a static source IP and changing it is a support ticket, not a config edit.
If you cannot rule those out, the safer sequence is: tag it
pending-release-YYYY-MM-DD, leave it a fortnight, then release. $3.65 is a
cheap insurance premium against an outage you cause yourself.
Why does nothing tell you about this?
Because no component is failing. The address exists, it is allocated, it is billing. That is all correct behaviour.
AWS Cost Explorer will show it if you go looking, aggregated into
EC2-Other, which is one of the least legible line items on the bill. Trusted
Advisor does flag idle Elastic IPs on the paid support tiers. Neither will
interrupt you about $3.65, and neither knows whether the address is genuinely
abandoned or deliberately reserved.
That is the general shape of small cloud waste: individually too small to alarm on, collectively significant, and invisible unless something is specifically looking for the absence of an association rather than the presence of a problem.
The wider check worth running
While you are in there, the same "allocated but attached to nothing" pattern applies to:
- Unattached EBS volumes — still billed at full rate, often left by
terminated instances with
DeleteOnTerminationset to false - Old snapshots with no parent volume
- NAT gateways in subnets with no traffic — $0.045/hour, roughly $32/month each, which makes a forgotten one an order of magnitude worse than an EIP
- Load balancers with no healthy targets, or no listeners at all
Every one of those bills for existing rather than for doing anything. They are the easiest savings on any AWS account and the least likely to be found, because finding them requires asking what is not connected to anything — which is not a question a dashboard is shaped to answer.