Stop and start an instance and one of its four addresses changes, which is the one in the firewall
Private IPv4, IPv6 and an Elastic IP all survive a stop and start. The auto-assigned public IPv4 does not: it is released on stop and a new one is assigned on start, and the old one can never be recovered. Associate an Elastic IP later and the public address is released then too. Every address costs the same $0.005 an hour, so the one that changes is the one with no reason to exist.
· Venerable Networks
An EC2 instance in a dual-stack public subnet has up to four addresses on its primary interface: a private IPv4, a public IPv4, an IPv6, and optionally an Elastic IP. Stop it for a maintenance window and start it again, and the EC2 instance addressing documentation gives each a different answer about whether it is still there.
Three persist
Private IPv4:
A private IPv4 address, regardless of whether it is a primary or secondary address, remains associated with the network interface when the instance is stopped and started, or hibernated and started, and is released when the instance is terminated.
IPv6:
An IPv6 address persists when you stop and start, or hibernate and start, your instance, and is released when you terminate your instance.
Elastic IP, from the Elastic IP documentation:
An Elastic IP address is static; it does not change over time.
A disassociated Elastic IP address remains allocated to your account until you explicitly release it.
Three addresses, three statements that they survive a stop. The private and IPv6 addresses belong to the network interface, and the interface persists. The Elastic IP belongs to the account, and the account persists.
One does not
The auto-assigned public IPv4 belongs to neither:
A public IP address is assigned to your instance from Amazon's pool of public IPv4 addresses, and is not associated with your AWS account. When a public IP address is disassociated from your instance, it is released back into the public IPv4 address pool, and you cannot reuse it.
And the events that release it, from the same page:
We release the public IP address when the instance is stopped, hibernated, or terminated. We assign a new public IP address when you start your stopped or hibernated instance.
A stop is a release. The start assigns a different address from the pool. Anything that recorded the old one, a DNS A record, a partner's firewall allow list, a known_hosts file, an API client's IP allow list, a monitoring probe, is now pointing at an address that belongs to no one, or soon to someone else. The instance comes up healthy. Nothing in its logs is wrong. The failures are at every system that memorised its public address.
The documentation says this is the design and names the alternative in the next paragraph:
If you require a persistent public IP address that can be associated to and from instances as you require, use an Elastic IP address instead.
The second way to lose it
The stop is the event everyone knows. The other release event is the one that catches people fixing the first:
We release the public IP address when you associate an Elastic IP address with the instance. We assign a new public IP address when you disassociate the Elastic IP address from your instance.
The sequence that produces an outage: an instance has a public IPv4 that is in a partner's allow list. Someone decides the address should be stable and associates an Elastic IP. The public IPv4 is released at that moment, and the instance is now reachable at the Elastic IP, which is a different address and is not in the partner's list. The change intended to prevent an address change caused one. The Elastic IP page makes the loss unambiguous:
You cannot reuse the public IPv4 address previously associated with the instance and you cannot convert that public IPv4 address to an Elastic IP address.
There is no promotion path. The Elastic IP is always a new address, and the public IPv4 it displaces is gone. The order of operations that avoids the outage is: allocate the Elastic IP, get it into every allow list and DNS record alongside the current address, and only then associate it.
The public DNS name follows the address, so hostname-based references survive while address-based ones do not:
When you associate an Elastic IP address with an instance that previously had a public IPv4 address, the public DNS host name of the instance changes to match the Elastic IP address.
Two cases where no new address appears
The "we assign a new public IP address" half of the rule has exceptions. Both are on the addressing page:
If we release the public IP address of your instance and it has a secondary network interface, we do not assign a new public IP address.
If we release the public IP address of your instance and it has a secondary private IP address that is associated with an Elastic IP address, we do not assign a new public IP address.
An instance that was given a second network interface after launch, or that has an Elastic IP on a secondary private address, loses its public IPv4 on stop and does not get one back. The instance was reachable before the maintenance window and is not reachable after it, at any public IPv4 address, and no setting was changed. The subnet's auto-assign attribute still says yes. The condition that suppresses the reassignment is a property of the instance's interface layout, and nothing surfaces it at stop time.
The address that changes is the one with no reason to exist
All four addresses have the same price. From the Elastic IP page:
AWS charges for all public IPv4 addresses, including public IPv4 addresses associated with running instances and Elastic IP addresses.
The VPC pricing page puts the rate at $0.005 an hour for an in-use public IPv4 and the same for an idle one. So an auto-assigned public IPv4 and an Elastic IP cost identical amounts. The only differences are that the Elastic IP survives a stop, can be moved to another instance, and counts against a quota of five per Region by default. The auto-assigned address has none of those properties and the same bill.
Which leaves two defensible configurations for an instance that needs a public IPv4, and the auto-assigned one is not either of them:
| Need | Configuration | Cost per hour |
|---|---|---|
| A public address anyone will record | Elastic IP, associated before anything records it | $0.005 |
| A public address nothing will record | Auto-assigned public IPv4, and accept that it changes | $0.005 |
| No public address | Auto-assign off; NAT Gateway, load balancer, or Instance Connect Endpoint for reach | $0 for the instance |
The second row is a real case: a fleet behind a load balancer where the instances need outbound internet and nothing ever connects inbound to them by address. Everything else that has a public IPv4 either should have an Elastic IP or should not have a public address at all. The addressing page's optimisation list says the same thing from the cost side, recommending that auto-assign be turned off on subnets and that load balancers, NAT Gateways and Instance Connect Endpoint take the place of per-instance public addresses.
What to do with it
Audit for public IPv4 without an Elastic IP. Any instance whose public address is auto-assigned, and that appears in anyone's allow list or DNS, is one stop-start from an outage. describe-instances with PublicIpAddress present and no matching describe-addresses entry is the list.
Allocate and distribute the Elastic IP before associating it. Association releases the current public address immediately. The new address has to already be everywhere the old one was.
Check the interface layout before a stop. A secondary network interface or an Elastic IP on a secondary private address means no public IPv4 after the start. If the instance needs one, give it an Elastic IP on the primary interface first.
Prefer the hostname where you can. The public DNS name tracks whichever public address the instance currently has. A partner who allow-lists a hostname survives both release events; one who allow-lists an address survives neither.
Treat auto-assigned public IPv4 as a cost with no benefit. It bills like an Elastic IP and behaves like a lease. Turn it off at the subnet unless the instances genuinely never receive inbound connections by address.
The same shape as the AZ that is not the same place in two accounts: an identifier that looks stable, is recorded as if it were, and is documented as not being. The documentation is clear and short. The systems that memorised the address never read it.