
AWS ALB Fixed IP: Using Global Accelerator for Static Addresses

How to get fixed IP addresses for an AWS ALB with Global Accelerator
An AWS Application Load Balancer gives you a DNS name, not client-facing addresses you can promise to another company forever. The practical workaround is to publish the two anycast IPv4 addresses from AWS Global Accelerator and route that traffic to the ALB behind the scenes.
Application Load Balancers are great until someone asks, "What IP addresses should we whitelist?"
That is where the fun starts. The addresses behind the ALB name can change as AWS scales and maintains the service. Telling a customer to whitelist whatever resolves today is not architecture. It is a calendar reminder for a future outage.
This keeps the firewall conversation simple without replacing your load balancer, target groups, certificates, listener rules, or the other ALB machinery you already use.
Quick answer
Use this pattern when the other side only accepts IP-based allowlists, but your service still needs ALB features such as HTTPS listeners, host routing, path routing, target groups, and health checks.
Implementation checklist:
- Create a Global Accelerator accelerator.
- Add a TCP listener, usually on port 443.
- Create an endpoint group in the same Region as the ALB.
- Register the ALB as the endpoint.
- Send both accelerator IPs to the firewall owner.
- Add a Route 53 alias to the accelerator if clients can connect by name.
The pattern looks like this:
Client network -> allowlist 2 Global Accelerator IPs -> AWS edge location -> Global Accelerator listener :443 -> regional endpoint group -> Application Load Balancer -> targets
Whitelisting, allowlisting, firewall exception, "please make networking stop yelling" - same practical problem.
Why ALB alone does not work
An ALB is addressed by DNS:
my-api-1234567890.eu-west-1.elb.amazonaws.com
That DNS name resolves to AWS-managed addresses. They are not yours, they are not fixed, and they are not a contract.
You can put a friendly name in Route 53:
api.example.com -> my-api-1234567890.eu-west-1.elb.amazonaws.com
That helps humans. It does not help a firewall that only accepts destination IPs.
Do not solve this by resolving the ALB name and sending the current addresses to a customer. Those addresses can change. The customer will eventually block your production traffic and then everyone gets to pretend DNS was the surprising part.
How Global Accelerator gives an ALB fixed inbound IPs
AWS Global Accelerator creates a fixed entry point for your application.
For an IPv4 accelerator, AWS gives you two static anycast IP addresses:
203.0.113.10 203.0.113.11
Those are the addresses your customer allowlists as outbound destinations. You can point your own DNS name at them:
api.example.com -> Global Accelerator alias
or, when the other side insists on raw IPs, hand them the two accelerator addresses.
Global Accelerator can use an Application Load Balancer as a standard accelerator endpoint. It also monitors endpoint health and can route to another Region if you add one later.
The important detail: the two Global Accelerator IPs are client-facing destination IPs. They are not the source IPs your ALB sees. Do not create an ALB security group rule that says "allow inbound from these two Global Accelerator IPs" and expect it to work. That is the common foot-gun, and it wears steel-toed boots.
Configure AWS Global Accelerator for an ALB with Terraform
Assume you already have an ALB listening on HTTPS.
The Global Accelerator pieces are:
- An accelerator
- A listener on TCP 443
- An endpoint group in the ALB Region
- The ALB as an endpoint
"aws_globalaccelerator_accelerator" "api" { name = "api-prod" ip_address_type = "IPV4" enabled = true attributes { flow_logs_enabled = false } } "aws_globalaccelerator_listener" "https" { accelerator_arn = aws_globalaccelerator_accelerator.api.id protocol = "TCP" client_affinity = "NONE" port_range { from_port = 443 to_port = 443 } } "aws_globalaccelerator_endpoint_group" "eu_west_1" { listener_arn = aws_globalaccelerator_listener.https.id endpoint_group_region = "eu-west-1" traffic_dial_percentage = 100 endpoint_configuration { endpoint_id = aws_lb.api.arn weight = 128 client_ip_preservation_enabled = true } }
After terraform apply, output the addresses:
"global_accelerator_ips" { value = aws_globalaccelerator_accelerator.api.ip_sets[0].ip_addresses }
Example output:
global_accelerator_ips = [ "203.0.113.10", "203.0.113.11", ]
These are the addresses to give to the other side for inbound access to your service from their point of view. They allow outbound traffic to those destination IPs. You keep your ALB behind the accelerator.
Add DNS without losing the fixed IPs
Create an alias record for the accelerator DNS name.
"aws_route53_record" "api" { zone_id = aws_route53_zone.example.zone_id name = "api.example.com" type = "A" alias { name = aws_globalaccelerator_accelerator.api.dns_name zone_id = aws_globalaccelerator_accelerator.api.hosted_zone_id evaluate_target_health = false } }
Customers that can allowlist by FQDN can use:
api.example.com
Customers that require IPs use the two accelerator addresses. Yes, both. Sending only one is how you turn high availability into a coin toss with extra paperwork.
Protect the ALB from direct access
Global Accelerator solves the fixed destination IP problem. It does not automatically make an internet-facing ALB impossible to reach directly through its own DNS name.
If the ALB is internet-facing, someone can still try:
curl https://my-api-1234567890.eu-west-1.elb.amazonaws.com
That bypasses your pretty api.example.com name and goes straight to the ALB. Security groups and AWS WAF still apply, but the request did not enter through the Global Accelerator IPs.
The cleaner pattern is to use an internal ALB as the accelerator endpoint. Global Accelerator supports internal Application Load Balancer endpoints and creates elastic network interfaces in your VPC to deliver the traffic.
"aws_lb" "api" { name = "api-prod" internal = true load_balancer_type = "application" subnets = module.vpc.private_subnets security_groups = [aws_security_group.alb.id] }
Then allow the application port on the ALB security group. With client IP preservation enabled for an ALB endpoint, your application can still read the original client address from X-Forwarded-For.
"aws_security_group_rule" "alb_https_in" { type = "ingress" security_group_id = aws_security_group.alb.id protocol = "tcp" from_port = 443 to_port = 443 cidr_blocks = ["0.0.0.0/0"] }
That rule may look too open, but the ALB is internal. The point is that the ALB does not have a public route of its own. Traffic arrives through Global Accelerator into the VPC path AWS creates for the endpoint.
If you must keep the ALB internet-facing, add compensating controls:
- Use AWS WAF on the ALB.
- Require valid host headers.
- Require authentication at the application layer.
- Restrict known customer source ranges in the ALB security group if the client list is small and stable.
Do not rely on obscuring the ALB DNS name. Obscurity is not a control. It is a shrug with a certificate.
Keep the real client IP
For ALB endpoints, Global Accelerator and ALB preserve the original client IP in X-Forwarded-For.
Your application will receive a header like this:
X-Forwarded-For: 198.51.100.25
If there are multiple proxies, the header can contain multiple addresses:
X-Forwarded-For: 198.51.100.25, 10.0.12.34
Make sure your app or ingress layer knows which proxy chain it trusts. Blindly trusting every X-Forwarded-For value from the internet is how logs become fan fiction.
For nginx behind the ALB, configure trusted proxy ranges for your VPC or ALB layer, not the whole internet:
set_real_ip_from 10.0.0.0/8; real_ip_header X-Forwarded-For; real_ip_recursive on;
Adjust the CIDR to your actual network.
Verify the fixed IP setup
Get the accelerator IPs:
aws globalaccelerator list-accelerators \ --query 'Accelerators[?Name==`api-prod`].IpSets[].IpAddresses[]' \ --output text
Test HTTPS against each IP while sending the expected host header:
curl -v --resolve api.example.com:443:203.0.113.10 https://api.example.com/health curl -v --resolve api.example.com:443:203.0.113.11 https://api.example.com/health
Check the accelerator health:
aws globalaccelerator describe-endpoint-group \ --endpoint-group-arn "$ENDPOINT_GROUP_ARN" \ --query 'EndpointGroup.EndpointDescriptions[*].{EndpointId:EndpointId,HealthState:HealthState,Weight:Weight}' \ --output table
Check your application logs for the client IP:
grep 'X-Forwarded-For' /var/log/app/access.log
Or query ALB access logs in Athena:
SELECT client_ip, request_url, target_status_code, time FROM alb_logs WHERE request_url LIKE '%/health%' ORDER BY time DESC LIMIT 20;
Troubleshooting common errors
If traffic does not reach the ALB, check these first:
| Symptom | Likely cause | What to check |
|---|---|---|
curl --resolve times out | The accelerator endpoint is unhealthy or the ALB security group blocks traffic | Check describe-endpoint-group, ALB listener rules, target group health, and security group ingress |
| TLS certificate mismatch | The request reached the ALB with the wrong host name | Use --resolve api.example.com:443:<accelerator-ip> and make sure the ALB certificate covers api.example.com |
| Customer allowlisted one IP but traffic still fails sometimes | Only one Global Accelerator IP was added to the firewall | Give them both accelerator IPs |
| ALB is still reachable directly | The ALB is internet-facing | Use an internal ALB endpoint or add WAF, host-header checks, authentication, and source restrictions |
| App logs show a proxy IP instead of the client IP | The app does not trust the right proxy chain | Configure trusted proxy ranges and read X-Forwarded-For correctly |
The most common mistake is treating the two Global Accelerator IPs as source IPs for the ALB security group. They are destination IPs for clients. Your ALB will not see requests as coming from those two addresses.
Multi-Region is the obvious next step
You do not need multiple Regions to justify Global Accelerator. Fixed ingress IPs are already enough.
But once it is in place, adding another ALB in another Region is straightforward:
"aws_globalaccelerator_endpoint_group" "us_east_1" { listener_arn = aws_globalaccelerator_listener.https.id endpoint_group_region = "us-east-1" traffic_dial_percentage = 0 endpoint_configuration { endpoint_id = aws_lb.api_us_east_1.arn weight = 128 client_ip_preservation_enabled = true } }
Start with traffic_dial_percentage = 0, validate the stack, then dial traffic up when you are ready:
traffic_dial_percentage = 10
This is useful for migrations, blue-green deployments, and disaster recovery plans that contain fewer hopes and prayers.
Things to remember
Global Accelerator is a good fit when external parties need stable destination IPs for your AWS-hosted service.
Use this pattern when:
- Clients must allowlist fixed IPs.
- You want an ALB behind those fixed IPs.
- You may want regional failover later.
- You want to avoid managing proxy instances or static Elastic IP hacks.
Be clear about what it does not do:
- It does not give the ALB fixed IPs.
- It does not make an internet-facing ALB private.
- It does not let you use the two accelerator IPs as ALB security group sources.
- It does not replace application authentication or WAF.
The short version: if you need fixed IP addresses for an AWS ALB, use AWS Global Accelerator. ALB gives you flexible HTTP load balancing. Global Accelerator gives you two stable anycast IPs in front of it. Put them together when the network team on the other side says, "We need IPs, not DNS," and you would prefer not to build your own little networking sadness machine.
Need fixed IPs for your load balancer?
We can design and implement an AWS Global Accelerator setup in front of your ALB so customers get stable IPs to allowlist without losing HTTPS routing or health checks.

Frequently Asked Questions
Does an AWS Application Load Balancer have a static IP address?
No. An ALB is addressed by DNS name, and the underlying IP addresses can change as AWS scales or maintains the service, so they should never be hardcoded into a firewall rule.
Can I attach an Elastic IP to an Application Load Balancer?
No, Elastic IPs can only be attached directly to a Network Load Balancer, not an ALB. To get fixed IPs in front of an ALB, put AWS Global Accelerator in front of it instead.
How many IP addresses does AWS Global Accelerator provide?
An IPv4 accelerator provides two static anycast IP addresses, and both should be given to the other party since either one may carry traffic.
Are the Global Accelerator IP addresses what the ALB sees as the source IP?
No. Those two IPs are the client-facing destination addresses that customers allowlist; they are not the source IPs your ALB security group will see, so do not use them in an ALB ingress rule.
Does Global Accelerator make an internet-facing ALB private?
No. If the ALB is internet-facing, it can still be reached directly through its own DNS name. Use an internal ALB as the accelerator endpoint, or add AWS WAF, host-header checks, and application authentication as compensating controls.
How do I preserve the real client IP address when using Global Accelerator?
Enable client IP preservation on the endpoint and read the original address from the X-Forwarded-For header, making sure your app or reverse proxy only trusts the known proxy IP ranges.
Can Global Accelerator also help with multi-Region failover?
Yes. Once an accelerator is in place, you can add an endpoint group in another Region and gradually shift traffic to it using the traffic dial percentage, which is useful for migrations and disaster recovery.
What should I send a customer who needs to allowlist my service by IP?
Send both Global Accelerator IPv4 addresses, not just one, since either address can carry production traffic and sending only one risks an eventual outage.





