AWS Error Guide: 'AddressLimitExceeded' — Reclaim and Raise the Elastic IP Quota
Fix EC2 AddressLimitExceeded: release unused Elastic IPs, reclaim leaked EIPs, raise the per-region quota, and cut idle Elastic IP hourly cost.
- #aws
- #cloud
- #troubleshooting
- #errors
Stuck on this AWS with AI error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
AWS caps the number of Elastic IP addresses you can allocate per region (5 by default, adjustable via Service Quotas). When you call AllocateAddress and you are already at the cap, EC2 rejects it with AddressLimitExceeded. Because unused Elastic IPs also incur an hourly charge, this error usually means you have both a quota problem and a small ongoing bill from addresses nobody released.
You will see it from the CLI or SDK:
An error occurred (AddressLimitExceeded) when calling the AllocateAddress operation: The maximum number of addresses has been reached.
Terraform or an ASG launch template surfaces the same during a NAT gateway or instance provisioning step:
Error: allocating EC2 EIP: AddressLimitExceeded: The maximum number of addresses has been reached.
It occurs when the per-region Elastic IP quota is reached — typically because old, unassociated EIPs from deleted instances, NAT gateways, or load balancers were never released.
Symptoms
AllocateAddressfails withAddressLimitExceededwhen creating a NAT gateway, instance EIP, or NLB.- Terraform/CloudFormation deploy fails on an
aws_eip/ EIP resource. - The account has several
unassociatedElastic IPs, some possibly forgotten and billing hourly. - The failure appears in a new region where the default quota is still 5.
aws ec2 allocate-address --domain vpc
An error occurred (AddressLimitExceeded) when calling the AllocateAddress operation: The maximum number of addresses has been reached.
Common Root Causes
1. Unassociated Elastic IPs never released
The most common cause: EIPs left over after their instance, NAT gateway, or LB was deleted, still counting against the quota (and billing).
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].[PublicIp,AllocationId]' --output text
52.0.0.10 eipalloc-REDACTED
52.0.0.11 eipalloc-REDACTED
Two EIPs are associated with nothing — reclaimable immediately.
2. Genuinely at the default quota
A workload legitimately needs more than 5 EIPs (multiple NAT gateways across AZs, several public endpoints) and the default cap is too low.
aws service-quotas get-service-quota \
--service-code ec2 --quota-code L-0263D0A3 \
--query 'Quota.[QuotaName,Value]' --output text
EC2-VPC Elastic IPs 5.0
The effective limit is 5; a multi-AZ NAT design alone needs 3, leaving little room.
3. A leaked EIP per deploy in CI
An IaC pipeline that allocates an EIP but does not always release it on teardown leaks one address per failed run.
aws ec2 describe-addresses \
--query 'Addresses[?Tags[?Key==`ManagedBy` && Value==`ci`]].[PublicIp,AssociationId]' --output text
52.0.0.20 None
52.0.0.21 None
52.0.0.22 None
Three CI-tagged EIPs, none associated — leaks from aborted pipeline runs.
4. New region with the default cap
Expanding into a new region resets the quota to the default 5, catching a workload designed around a raised limit elsewhere.
aws ec2 describe-addresses --region eu-central-1 --query 'length(Addresses)' --output text
5
Already at 5 in a freshly used region.
5. NAT gateways and NLBs consuming EIPs quietly
Each NAT gateway and each AZ of a public NLB with a fixed EIP consumes one, so a multi-AZ design uses several without an obvious “instance” attached.
aws ec2 describe-addresses \
--query 'Addresses[?NetworkInterfaceId!=null].[PublicIp,NetworkInterfaceId]' --output text
52.0.0.30 eni-REDACTED
52.0.0.31 eni-REDACTED
Associated EIPs are attached to NAT/NLB ENIs — legitimate, but they count.
Diagnostic Workflow
Step 1: List every Elastic IP and its association state
aws ec2 describe-addresses \
--query 'Addresses[].[PublicIp,AllocationId,AssociationId,InstanceId]' --output text
Rows with a null AssociationId are unassociated — reclaimable and billing hourly.
Step 2: Count against the quota
aws ec2 describe-addresses --query 'length(Addresses)' --output text
aws service-quotas get-service-quota --service-code ec2 --quota-code L-0263D0A3 \
--query 'Quota.Value' --output text
Compare the count to the quota to confirm you are at the cap.
Step 3: Separate reclaimable from in-use
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].[PublicIp,AllocationId,Tags]' --output json
Verify each unassociated EIP is truly abandoned (tags, naming) before releasing — a just-allocated EIP waiting to be attached is also unassociated.
Step 4: Trace where they came from
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=AllocateAddress \
--query 'Events[].[EventTime,Username]' --output text | head
This shows which principal or pipeline allocated the addresses, pointing at a leaking source.
Example Root Cause Analysis
A Terraform apply that added a third-AZ NAT gateway failed with AddressLimitExceeded. The account was in the default 5-EIP region.
Listing addresses showed only two were actually associated; three were orphaned:
aws ec2 describe-addresses --query 'Addresses[?AssociationId==null].[PublicIp,AllocationId]' --output text
52.0.0.20 eipalloc-REDACTED
52.0.0.21 eipalloc-REDACTED
52.0.0.22 eipalloc-REDACTED
CloudTrail tied all three to a CI role from failed runs weeks earlier — the pipeline allocated an EIP for a test NAT gateway but errored before the release step, leaking one each time:
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=AllocateAddress \
--query 'Events[].Username' --output text | sort | uniq -c
3 ci-network-role
2 terraform-prod
Releasing the three orphans freed the quota and the apply succeeded:
for a in eipalloc-A eipalloc-B eipalloc-C; do aws ec2 release-address --allocation-id $a; done
The durable fix wrapped the CI teardown in a trap that always releases allocated EIPs, and raised the region’s EIP quota to 10 to match the multi-AZ NAT design.
Prevention Best Practices
- Release Elastic IPs as soon as their resource is gone; unassociated EIPs both consume the quota and bill hourly.
- Run a periodic sweep for
AssociationId==nulladdresses and reclaim confirmed orphans. - Wrap IaC/CI EIP allocation in guaranteed teardown (Terraform lifecycle, a
trapon exit) so failed runs do not leak addresses. - Request a Service Quotas increase for
EC2-VPC Elastic IPsin every region where a multi-AZ NAT/NLB design legitimately needs more than 5. - Prefer NAT gateway auto-assigned public IPs or IPv6 egress-only gateways where you do not need a stable, owned EIP, reducing EIP pressure entirely.
Quick Command Reference
# All EIPs and whether they are associated
aws ec2 describe-addresses \
--query 'Addresses[].[PublicIp,AllocationId,AssociationId]' --output text
# Unassociated (reclaimable) EIPs
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].[PublicIp,AllocationId]' --output text
# Release an orphaned EIP
aws ec2 release-address --allocation-id <eipalloc-id>
# Current EIP quota for the region
aws service-quotas get-service-quota --service-code ec2 --quota-code L-0263D0A3 \
--query 'Quota.Value' --output text
# Request an increase
aws service-quotas request-service-quota-increase \
--service-code ec2 --quota-code L-0263D0A3 --desired-value 10
Conclusion
AddressLimitExceeded means you have hit the per-region Elastic IP quota. The usual root causes:
- Unassociated EIPs from deleted resources never released.
- A workload legitimately exceeding the default 5-EIP cap.
- A CI/IaC pipeline leaking one EIP per failed run.
- A new region still on the default quota.
- Multi-AZ NAT gateways and NLBs quietly consuming addresses.
List every address, reclaim the truly orphaned ones (which also stops their hourly charge), guarantee EIP release in automation, and raise the quota where a multi-AZ design genuinely needs it.
Fixed it? Get 500 AWS with AI & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.