Unused public IPv4 addresses: find and release them
AWS bills every public IPv4 address by the hour, in use or not, and Google Cloud bills reserved static IPs that sit unused. How to find and release them.
Contents
In short
- Since February 2024, AWS charges for every public IPv4 address, attached or not.
- An Elastic IP attached to nothing is pure waste.
- Check DNS records before releasing: a released address is gone for good.
Public IPv4 addresses used to be free on AWS while attached to a running instance. That changed on February 1, 2024: since then every public IPv4 address bills by the hour, attached to a service or not. Google Cloud bills static addresses too, and charges more for one that sits reserved and unused.
One address is small money. The problem is that nobody owns them. Elastic IPs outlive the instances they were allocated for, and reserved static IPs outlive the load balancers they were meant for. This guide shows how to find the ones attached to nothing and release them safely.
What an address costs
On AWS, as of October 2026, the VPC pricing page lists $0.005 per hour for each public IPv4 address, whether it is in use or idle. That is about $3.65 a month per address. New accounts get 750 free hours a month for their first 12 months.
On Google Cloud, in us-central1 as of October 2026, external IP pricing depends on what the address does:
| Address | Price per hour |
|---|---|
| Static IP, reserved but unused | $0.01 |
| In use on a standard VM | $0.005 |
| In use on a Spot or preemptible VM | $0.0025 |
| Used by Cloud NAT | $0.005 |
| On a forwarding rule | Free |
A reserved address attached to nothing costs twice as much as one in use: about $7.30 a month. A static IP attached to a stopped VM still counts as in use.
Find idle Elastic IPs on AWS
An Elastic IP with no association is attached to nothing. Addresses are regional, so check every region you use:
for r in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
aws ec2 describe-addresses --region "$r" \
--query 'Addresses[?AssociationId==null].[PublicIp,AllocationId,Tags[?Key==`Name`]|[0].Value]' \
--output text | awk -v r="$r" '{print r "\t" $0}'
done
Each line is a region, an address, its allocation ID and its Name tag, if it has one.
Two more cases bill without doing much:
- An Elastic IP on a stopped instance. It is associated, so the query above skips it, but you are charged for Elastic IPs on stopped instances. If the instance is stopped for good, the address is idle too. See how to find and stop idle EC2 instances.
- Auto-assigned public IPs. Instances in a subnet that assigns public IPs on launch each get one, and each one bills. List those subnets:
aws ec2 describe-subnets \
--query 'Subnets[?MapPublicIpOnLaunch].[SubnetId,VpcId,AvailabilityZone]' --output table
AWS announced Public IP Insights, in VPC IP Address Manager, alongside the charge. It gives one view of the public IPv4 addresses in your account, which helps when you have many.
Find unused static IPs on Google Cloud
A static address that is reserved but attached to nothing has the status RESERVED. In use, it shows IN_USE:
gcloud compute addresses list --filter="status=RESERVED" \
--format="table(name,address,region.basename(),addressType)"
Run it per project. Internal addresses show up too; this guide is about external ones, so check the addressType column.
Check before you release
A released address is gone. You can’t count on getting the same one back, and anything that still points at it breaks. Before releasing, check:
- DNS. Search your zones for the address. In Route 53:
aws route53 list-resource-record-sets --hosted-zone-id Z0123456789ABCDEFGHIJ \
--query "ResourceRecordSets[?ResourceRecords[?Value=='203.0.113.10']]"
- Allowlists. Partners, payment providers and customers sometimes allowlist an address for outbound traffic. An idle Elastic IP may exist only to keep that address for a server that will come back. If someone can name that reason, tag the address with it and keep it.
- Infrastructure code. Search your repositories for the address and the allocation ID. If Terraform or CloudFormation manages it, remove it there, or the next apply recreates it.
Release them
On AWS, release an Elastic IP by its allocation ID:
aws ec2 release-address --region us-east-1 --allocation-id eipalloc-0123456789abcdef0
If it is still associated, for example with a stopped instance, disassociate it first:
aws ec2 disassociate-address --region us-east-1 --association-id eipassoc-0123456789abcdef0
On Google Cloud, delete the reserved address in its region, or with --global for a global one:
gcloud compute addresses delete my-address --region=us-central1
On Azure, a public IP with no IP configuration and no NAT gateway is attached to nothing:
az network public-ip list \
--query "[?ipConfiguration==null && natGateway==null].[name,resourceGroup,ipAddress]" -o table
az network public-ip delete --resource-group my-rg --name my-public-ip
Need fewer public IPv4 addresses
Releasing idle addresses stops the waste. Needing fewer addresses lowers the bill for the ones in use. In general terms:
- Put services behind a load balancer instead of giving each instance its own public address.
- Keep instances in private subnets and send outbound traffic through a NAT gateway, so many instances share a few addresses. Weigh the NAT gateway’s own hourly and data processing charges against what you save.
- Use IPv6 where your clients and dependencies support it.
- Turn off public IP auto-assignment on subnets that don’t need it.
Keep it from coming back
Tag every address with an owner and a reason when you allocate it. Release Elastic IPs in the same change that terminates their instance, in code, so the two can’t drift apart. Review idle addresses monthly with the commands above. Omni FinOps flags unassociated Elastic IPs and reserved Google Cloud addresses on every refresh, and every lead reminds you to check DNS first. The AWS and Google Cloud pages list everything else it checks.
Mateo Vargas writes Omni FinOps’ cost guides, from the same rules the product runs on every refresh. Prices are list prices in us-east-1 or us-central1 as of October 11, 2026; check your region’s pricing page.