TL;DR: Every Elastic IP reserved but attached to nothing bills at $0.005/hour (~$3.60/month) — trivial per-resource, which is exactly why it accumulates silently into "wait, we have 200 EIPs?" Releasing truly-unassociated EIPs is the single most fire-and-forget cost action in AWS: outside a few tagged exceptions (partner allowlists, hardcoded DNS), nothing needs an unattached EIP to stay reserved. The one caution: release is irreversible — you get an IP back, not the IP.
The numbers
- ~$3.60/month per unassociated EIP ($0.005/hr). (As of 2024 AWS bills all EIPs — even attached ones — at this rate; releasing the unattached ones is the only fully-free move.)
- A stopped instance's EIP still bills — the old "free if attached to a running instance" carve-out never covered stopped instances.
- A multi-year unaudited account often holds 50–300 unassociated EIPs accumulating at 5–10/month from CI-driven churn — $2K–13K/year recovered.
- Field examples: a SaaS onboarding bug leaked ~200 EIPs = $720/mo ($8,640/yr), cleaned in one hour + a 30-min fix; 8 EIPs from a cancelled launch released for $345/yr (new ones allocated with zero drama when the project later relaunched).
Do this
- List them:
aws ec2 describe-addresses --query "Addresses[?AssociationId==null]"— sort/count and note the estimated savings. - Triage by tag and DNS — skip anything tagged
purpose=/partner=/do-not-release=true, and grep Route 53 (public and private) for any long-TTL record pointing at the address. - Cross-reference IaC — any EIP not declared in Terraform/CloudFormation was allocated manually and forgotten (more deletable).
- Post a "releasing these Friday unless yours" list, wait 48h, then bulk-release:
aws ec2 release-address --allocation-id <id>in a loop (or console multi-select). - Prevent recurrence — lint IaC to fail on
aws_eipwithout a matchingaws_eip_association, pairallocate-address/release-addressin scripts, and add a Config rule flagging EIPs unattached >7 days.
Gotchas
- Release is irreversible for the specific address — it returns to AWS's regional pool within hours, so tag anything a partner firewall or long-TTL DNS record depends on and skip it.
- NAT Gateway EIPs won't appear here (they're associated with the NAT) — the NAT itself is the far bigger cost (~$32/mo+).
us-east-1re-allocation can be harder under high demand — don't release if you specifically need a us-east-1 IP within hours.- Cleanup without prevention is a hobby — if the same EIPs re-flag, you have a creation problem (IaC or offboarding scripts leaking), not a cleanup one.
Skip this if
- The EIP is a real partner-allowlist or hardcoded-DNS dependency — tag it explicitly (
purpose=partner-allowlist,do-not-release=true), document the relationship, and consider AWS Global Accelerator anycast IPs for more resilient static addressing. - Don't hoard "spare" EIPs as a backup pool — that's ~$43/yr each in pure overhead; you can allocate spares in seconds during a real incident. Same-shape cleanups: Trusted Advisor — Idle Load Balancers and the pricier cousin NAT Gateway Consolidation. Parent: Trusted Advisor Cost Optimization.