You're scanning your AWS bill and you hit a line item that stops you cold: you're being charged for an IP address. Not a server, not storage — an address. It's a small number, but it makes no sense, and a charge you can't explain is a charge worth understanding. Here's exactly what it is, why it surprises everyone, and how to make it go away.
Why would AWS charge me for an IP address I'm not using?
This is the part that breaks people's mental model: with a classic Elastic IP (EIP), using it is free, and hoarding it costs money.
An Elastic IP attached to a running instance has historically been free. But an EIP you've allocated and left unattached — sitting in your account, reserved to you, pointed at nothing — bills by the hour. The pricing is deliberately inverted on purpose. IPv4 addresses are a scarce, finite resource, so AWS charges you for reserving one you're not putting to work. That inversion — free when used, billed when idle — is exactly why it feels backwards when you see it.
What changed in 2024?
The old mental model ("only unattached EIPs cost money") is now out of date, and this is the fact most competing posts get wrong or omit.
Since 1 February 2024, AWS charges roughly $0.005 per hour — about $3.60/month — for every public IPv4 address, whether it's attached to a running instance or not. That includes the address on your running EC2 instances, not just the abandoned ones. AWS made this change to reflect the growing scarcity (and cost) of IPv4 and to nudge workloads toward IPv6.
The ~$0.005/hour figure is the standard public IPv4 rate at the time of writing and is rounded for clarity. AWS changes prices and rates vary by region — check the AWS VPC pricing page for the exact number before you make decisions based on it.
So the total has two parts: a small unavoidable charge on the IPs you're actively using, and a fully avoidable charge on every address you've allocated and abandoned. Across a sprawling account with a handful of forgotten EIPs, the avoidable part adds up — and it's pure waste.
The unavoidable half has a longer-term fix worth knowing about: IPv6 addresses are free. AWS's whole reason for the 2024 change was to make IPv4's scarcity visible in the bill and push new architectures toward IPv6. You're not going to migrate a production estate overnight, but for greenfield workloads — a new VPC, a fresh service behind an IPv6-capable load balancer — designing for IPv6 sidesteps the per-address charge entirely. For everything already running on IPv4, the practical win is simpler: stop paying for the addresses you've abandoned.
Where do these abandoned IPs even come from?
Nobody allocates an Elastic IP intending to abandon it. They pile up as a side effect of other changes:
- You terminated an instance that had an EIP attached — the instance is gone, but the EIP was allocated separately and stays behind in your account.
- You deleted a NAT Gateway or replaced a load balancer, and the address it used was left allocated. This one is common right after a networking cost cleanup — teams who go looking for the reason a NAT Gateway bill is so large often delete two or three redundant gateways and inherit an equal number of stranded addresses.
- A migration or a blue/green cutover left the old address stranded once traffic moved to the new one.
In every case the resource that justified the IP is gone, but the IP itself lingers — billing quietly until someone notices.
How do I find and release them?
Finding unattached EIPs is a one-liner. An Elastic IP with no InstanceId (and no association) is attached to nothing:
aws ec2 describe-addresses \
--query 'Addresses[?!InstanceId && !AssociationId].[PublicIp,AllocationId]' \
--output table
Anything that comes back is an EIP you're paying for and not using. Note that this only covers Elastic IPs — the 2024 change also bills the auto-assigned public IPs on running instances, which don't show up in describe-addresses at all. To see your full IPv4 footprint, list running instances with a public IP (aws ec2 describe-instances --query 'Reservations[].Instances[?PublicIpAddress].[InstanceId,PublicIpAddress]') alongside the EIP list above; every address across both is now $3.60/month.
To release an unattached EIP (in the Console: EC2 → Elastic IPs → select → Release Elastic IP addresses):
aws ec2 release-address --allocation-id eipalloc-0123456789abcdef0
When you release an EIP, you give the address back to AWS's pool — and you will almost
certainly not get the same address again. Before you release one, make sure nothing external
still depends on it: a DNS A record pointing at it, a partner's firewall allowlist, a
hard-coded value in a third party's config, or an SSL/monitoring endpoint. Releasing an address
that something still references will break that thing silently. When in doubt, confirm the address
appears nowhere in your DNS and allowlists before you let it go.
What else should I check?
Abandoned Elastic IPs are usually a symptom of the same neglect that leaves idle EC2 instances running — the terminated instance that stranded the EIP often had siblings that are still on and doing nothing. If you're cleaning up stray addresses, it's worth checking the compute too. See how to find idle EC2 instances.
An Elastic IP is a few dollars a month, though, so treat it as the last item on the list rather than the first. If you are working through the bill properly, start where the money actually leaks — idle compute and oversized databases dwarf a handful of stray addresses, and the order you fix things in matters more than the number of things you fix.
The same "resource outlives what it justified" pattern shows up one layer over in DNS, too. A Route 53 hosted zone or health check for a domain that stopped mattering keeps billing its flat monthly fee with nothing left to point at, for exactly the reason a stranded EIP does — nothing about deleting the thing it served ever deletes the record pointing at it. How Route 53 pricing adds up covers that fee structure and how to find the zones and health checks worth cleaning up.
If GuardDuty is enabled on the account, know that releasing a stray Elastic IP won't move its bill on its own — GuardDuty's foundational protection prices VPC Flow Log and DNS query analysis by the gigabyte using its own independent copy of that traffic, not the flow logs or IPs you manage yourself. But retiring the actual resources behind those stray addresses (the idle instance, the decommissioned NAT Gateway) does shrink the real traffic volume GuardDuty gets billed to analyze, the same way it shrinks every other per-GB meter on the account. See what GuardDuty costs once it's on everywhere for how that volume-based pricing adds up across every Region and account you've turned it on in.
How do I find this across my whole AWS account?
One region's unattached EIPs are easy to spot. Every region's — plus the full picture of what your public IPv4 footprint is now costing under the 2024 pricing — is the tedious part. That's what a scan is for. Parsivex checks each region, flags Elastic IPs that are allocated but attached to nothing — and then keeps watching, so newly stranded addresses get caught before they quietly cost you again.
For what this finding means once it shows up in your report, see Unused Elastic IP, or read how scans work before you connect an account.