What it actually is
AWS Global Accelerator gives your application a small set of static IP addresses that are announced from AWS edge locations all over the world, and then carries the traffic from the edge to your endpoints over the AWS backbone instead of the public internet. The docs call these addresses anycast: the same two IPs are reachable from many places, and a client's packets land at whichever edge is closest to it.
The mental model the docs bury: this is a layer 4 service, not a cache and not a DNS trick. A CDN stores copies of your content near users. Route 53 answers a name lookup with an address that you hope the client keeps using. Global Accelerator does neither. The docs say it terminates TCP connections from clients at the edge and, almost concurrently, opens a new TCP connection to your endpoint. The client talks to a nearby edge, AWS talks to your Region, and nothing is stored in between. Every byte still has to come from your origin.
What you buy is a stable front door. The two addresses (four if you choose dual-stack) stay assigned for as long as the accelerator exists, even while it is disabled. You put them in firewall allow lists and client configs once, and then you add Regions, run blue/green, or fail over, without any client learning a new address.
The model
There are five nouns, and they nest.
An accelerator is the top object. It owns the static IPs and a DNS name of the form a1234567890abcdef.awsglobalaccelerator.com. A listener belongs to an accelerator and declares the protocol (TCP, UDP, or both) and up to 10 port ranges. An endpoint group belongs to a listener and is tied to exactly one AWS Region. An endpoint belongs to an endpoint group and is one of four things for a standard accelerator: an Application Load Balancer, a Network Load Balancer, an EC2 instance, or an Elastic IP address.
Two knobs steer traffic. The traffic dial sits on the endpoint group, runs from 0 to 100, and defaults to 100. Per the docs, it applies only to traffic that was already going to that group under optimal routing, and the rest spills to other Regions. A dial of 50 means that of 100 requests aimed at a Region, 50 are accepted and 50 go elsewhere. The endpoint weight sits on the endpoint, runs up to 255, defaults to 128, and splits traffic inside a group in proportion to weight over total weight. A weight of 0 stops traffic to that endpoint.
Two behaviors matter more than the diagram suggests. First, changes apply to new connections only. The docs say Global Accelerator keeps directing established connections to their endpoint until the idle timeout, even if that endpoint is now unhealthy or has been removed. The idle timeouts are fixed: 340 seconds for TCP and 30 seconds for UDP, and keep-alive packets do not reset them; you must send at least one byte of data. Second, if no endpoint in a group is healthy, Global Accelerator routes requests to all endpoints in the group rather than dropping them.
There is also a second accelerator type. A custom routing accelerator maps a specific user to a specific destination (a particular EC2 instance and port) inside VPC subnets, which is the pattern for game servers and VoIP. It does no health checks and no failover, because you choose the destination. Everything below is about the standard type.
One operational quirk: every Global Accelerator API call must be made in US West (Oregon), us-west-2, regardless of where your endpoints are. Quota increases go through Service Quotas in us-east-1.
When to use it, when not to
The services people confuse it with are CloudFront and Route 53. The difference is the layer each one works at.
Global Accelerator | CloudFront | Route 53 failover/latency routing | |
|---|---|---|---|
Layer | TCP and UDP, any port | HTTP and HTTPS | DNS answers |
Caches content | No | Yes | No |
Client-facing address | 2 static anycast IPs | Changing edge IPs behind a name | Whatever the record says |
Failover for new connections | Health-based, no DNS involved | Origin failover on errors | Depends on TTL and resolver behavior |
Good for | Non-HTTP protocols, IP allow lists, fast regional failover, gaming, VoIP | Cacheable web content, static assets, HTTP APIs at the edge | Cheap global routing where clients honor TTLs |
The honest rule: if your traffic is cacheable HTTP, CloudFront is the better first answer and usually cheaper. If it is not HTTP at all (MQTT, a custom TCP protocol, UDP game traffic), or a customer insists on a fixed pair of IPs to allow list, or you need a regional failover that does not wait for DNS caches to expire, Global Accelerator is the right tool. The AWS docs make the same pitch: stable entry points, nearest-edge ingress, and instant re-routing when the primary Region is failing.
When not to use it: a single-Region app with users in one geography gains little for a recurring fee. Static content you could cache gains nothing at all. And if all you want is a pretty DNS name in front of one load balancer, you do not need an accelerator.
What it costs
There are two meters and one trap.
The fixed fee is $0.025 per hour per accelerator, charged for every full or partial hour until the accelerator is deleted. AWS prices a 30-day month at $18. The trap lives in the same sentence: enabled and disabled accelerators are both charged. Disabling is not a pause button. Only deletion stops the meter.
The second meter is the Data Transfer-Premium fee, charged per GB on the dominant traffic direction only, calculated hourly. The dominant direction is either inbound to your application or outbound to users, whichever is larger in that hour. The rate depends on the source Region and the destination edge location. A few cells from the current table, in USD per GB: US and Canada to the US, Mexico and Canada is $0.015; US and Canada to Europe is $0.015; US and Canada to most of Asia Pacific is $0.035; US and Canada to Australia and New Zealand is $0.105; Europe to Australia and New Zealand is $0.105. The same pricing page states that this is charged in addition to normal EC2 Data Transfer Out fees. So Global Accelerator never replaces your egress bill, it adds to it.
AWS's own worked example is a North America accelerator moving 10,000 GB in a month, 60 percent outbound. Only the 6,000 GB outbound is billed: 5,000 GB to Europe at $0.015 is $75, and 1,000 GB to Asia Pacific at $0.035 is $35, so $110 of DT-Premium plus $18 fixed is $128. Standard public IPv4 charges also apply to the addresses used with accelerators; check the VPC pricing page for the current rate. The pricing page did not state a free tier, custom routing pricing or BYOIP charges, so do not assume one.
The practical consequence for architecture: the fixed fee is trivial, and DT-Premium is a per-GB tax that scales with traffic and with how far your users are from your Regions. Heavy download traffic to Australia is the expensive corner of the table. A chatty low-volume protocol is nearly free.
Cost of following along: the accelerator for about one hour is roughly 2.5 cents. Your two load balancers and two instances cost whatever they cost per hour in your Regions (see their pricing pages), and the test traffic is a few kilobytes. Budget a few dollars at most, and delete everything the same day.
The limits that bite
Per the current quotas page: 20 standard accelerators per account (adjustable), 10 custom routing accelerators (adjustable), 10 listeners per accelerator (adjustable), 10 port ranges per listener (not adjustable), and 10 endpoints per endpoint group (adjustable for NLB, EC2, EIP and VPC subnet groups, fixed for ALB-only and mixed groups). Endpoint groups and Regions across all listeners are capped at 42, and the cap is multiplicative: total listeners times endpoint groups must not exceed 42. Ten listeners with five Regions each blows through it.
The limits that hurt in practice are behavioral. Existing connections do not move, so a failover leaves long-lived TCP sessions pinned to a dead endpoint until the 340-second idle timer fires or the client reconnects. TCP fragments are dropped at the edge, so do not rely on fragmenting large TCP segments; UDP fragments are forwarded for reassembly at the endpoint. ICMP echo is answered at the edge and never reaches your endpoint, so a successful ping proves nothing about your application. The service is still growing its footprint: an October 2025 announcement added Asia Pacific (Thailand) and Asia Pacific (Taipei) as endpoint Regions, bringing the total to 33. Endpoints must be inside an AWS Region: ALBs, NLBs and EIPs in Local Zones are not supported. Certain old EC2 instance families (C1, CC1, CC2, CG1, CG2, CR1, CS1, G1, G2, HI1, HS1, M1, M2, M3, T1) cannot be endpoints. Dual-stack Elastic IPs cannot be endpoints, and an endpoint on a dual-stack accelerator must have client IP preservation enabled.
Client IP preservation deserves its own sentence. It works for ALBs, EC2 instances and NLBs that have security groups, and it does not work for NLBs without security groups or for Elastic IPs. Without it, your backend sees the accelerator's addresses rather than the client's. Also, AWS recommends that you disable cross-zone load balancing on NLB endpoints to avoid connection collisions, and that you do not also send traffic directly to the same endpoints over the internet.
Build it
The goal: one accelerator, one TCP listener on port 80, two endpoint groups (a primary and a secondary Region), a measured failover. I have not executed this exact script against a live account in this run, and I say so because the numbers you collect are yours to collect. The calls follow the API reference.
Prerequisites. Two internet-facing Application Load Balancers, one in us-east-1 and one in eu-west-1, each with an HTTP listener on port 80 forwarding to a target group with one instance. Make each instance return its own Region name in the response body (a one-line web server is enough). Python 3 with boto3. Note both ALB ARNs.
IAM. The AWS-managed GlobalAcceleratorFullAccess policy covers console and API work, including the EC2 and Elastic Load Balancing describe permissions that you need to add those resources as endpoints; a custom policy without them cannot add EC2 or ELB resources. You also need iam:CreateServiceLinkedRole for the service principal globalaccelerator.amazonaws.com, because the first accelerator creates the AWSServiceRoleForGlobalAccelerator role automatically, and a policy more restrictive than the documented one prevents creation.
import time, uuid
import boto3
# Global Accelerator control plane lives in us-west-2 only
ga = boto3.client("globalaccelerator", region_name="us-west-2")
ENDPOINTS = {
"us-east-1": "arn:aws:elasticloadbalancing:us-east-1:111122223333:loadbalancer/app/primary/abc123",
"eu-west-1": "arn:aws:elasticloadbalancing:eu-west-1:111122223333:loadbalancer/app/secondary/def456",
}
def token():
return str(uuid.uuid4())
acc = ga.create_accelerator(
Name="sl-demo-accelerator",
IpAddressType="IPV4",
Enabled=True,
IdempotencyToken=token(),
Tags=[{"Key": "project", "Value": "software-letters-demo"}],
)["Accelerator"]
acc_arn = acc["AcceleratorArn"]
listener = ga.create_listener(
AcceleratorArn=acc_arn,
Protocol="TCP",
PortRanges=[{"FromPort": 80, "ToPort": 80}],
ClientAffinity="NONE",
IdempotencyToken=token(),
)["Listener"]
listener_arn = listener["ListenerArn"]
groups = {}
for region, alb_arn in ENDPOINTS.items():
groups[region] = ga.create_endpoint_group(
ListenerArn=listener_arn,
EndpointGroupRegion=region,
TrafficDialPercentage=100,
EndpointConfigurations=[
{"EndpointId": alb_arn, "Weight": 128, "ClientIPPreservationEnabled": True}
],
IdempotencyToken=token(),
)["EndpointGroup"]["EndpointGroupArn"]
# Wait for the global propagation to finish
while ga.describe_accelerator(AcceleratorArn=acc_arn)["Accelerator"]["Status"] != "DEPLOYED":
time.sleep(15)
d = ga.describe_accelerator(AcceleratorArn=acc_arn)["Accelerator"]
print("DNS:", d["DnsName"])
print("IPs:", [ip for s in d["IpSets"] for ip in s["IpAddresses"]])
I deliberately did not set health check interval, threshold or path on these groups. The docs say that for ALB and NLB endpoints health comes from Elastic Load Balancing, not from Global Accelerator's own options: an ALB is healthy if every target group has at least one healthy target, and an NLB is healthy if at least one Availability Zone is healthy and the healthy target count meets minimum_healthy_targets. Those options exist for EC2 and Elastic IP endpoints, where the defaults are a 30 second interval (allowed range 10 to 30), a threshold count of 3 (1 to 10), TCP protocol, and the listener port.
Verification. Hit the accelerator and read which Region answered:
import urllib.request
def whoami(host, timeout=3):
try:
with urllib.request.urlopen(f"http://{host}/", timeout=timeout) as r:
return r.read().decode().strip()
except Exception as e:
return f"ERR {type(e).__name__}"
print(whoami(d["DnsName"])) # expect the Region closest to you
From a client near the US East Coast you should see us-east-1. A client in Europe should see eu-west-1. That is the nearest-Region routing, and it needs no DNS logic from you.
Experiment 1: the dial. Set the primary group's dial to 0 and watch new connections move.
ga.update_endpoint_group(EndpointGroupArn=groups["us-east-1"], TrafficDialPercentage=0)
for _ in range(10):
print(whoami(d["DnsName"]))
time.sleep(1)
The docs describe setting the dial to 0 as the maintenance move, and say settings apply to new connections only. Every urlopen opens a new connection, so you should see the answers flip to eu-west-1. Restore the dial to 100 afterward.
Experiment 2: the failover you measure. Stop the instance behind the primary ALB (or deregister it from its target group) and time how long until the accelerator answers from the secondary.
def measure(host, expect_not="us-east-1", poll=1.0, limit=600):
t0 = time.time()
while time.time() - t0 < limit:
who = whoami(host)
print(f"{time.time()-t0:6.1f}s {who}")
if who and not who.startswith("ERR") and who != expect_not:
return time.time() - t0
time.sleep(poll)
return None
# Stop the primary instance now, then run:
print("failover seconds:", measure(d["DnsName"]))
I am not going to quote a number, because AWS does not publish one: the docs say traffic shifts instantly for new connections once an endpoint is unhealthy, and give no figure. The time you see is dominated by something you control, which is how fast Elastic Load Balancing declares the target group unhealthy. With a target group checking every 30 seconds and requiring several failures, your measured gap will be a minute or more regardless of how fast Global Accelerator reacts afterwards. Tighten the target group's health check interval and unhealthy threshold, rerun the test, and compare. That one result is the real lesson of this article: the accelerator is fast, your health check budget is not.
Compare it with a DNS failover design. With DNS, even a perfect health check is followed by resolver caches and client caches that may ignore your TTL. Here, the clients keep the same two IPs and the next new connection simply lands elsewhere. Established connections, as noted above, stay where they are until they time out.
When it breaks
The accelerator stays IN_PROGRESS. Creation returns that status immediately; it is propagating. Poll until DEPLOYED before testing.
Everything times out from your laptop but the ALB works directly. Check that the ALB is internet-facing and that its security group allows the client. With client IP preservation on, the ALB sees the real client address, so a security group written for "the accelerator" will not match. Allow the client ranges you actually serve.
An EC2 or Elastic IP endpoint is always unhealthy. For UDP listeners, the docs say health checks use the listener port over TCP, so each endpoint needs a TCP server on that port or it is marked unhealthy regardless of its real state. Also allow inbound traffic from the Route 53 health checker ranges.
You cannot add an endpoint. The usual causes are an unsupported EC2 family, a Local Zone resource, a dual-stack Elastic IP, a dual-stack NLB with preservation enabled on an IPv4 accelerator, or a custom IAM policy lacking the EC2 and ELB describe actions.
Traffic keeps going to a dead endpoint after failover. That is the established-connection rule. Wait out the 340-second TCP idle timeout, or make clients reconnect on error.
The AWS CLI says the accelerator does not exist. Almost always the wrong Region. Add --region us-west-2.
delete-accelerator is refused. An accelerator that is enabled cannot be deleted. Disable it first.
Cleanup
Order matters: disable, wait, then delete from the leaves up. The meter runs until deletion, so do this the same day.
ga.update_accelerator(AcceleratorArn=acc_arn, Enabled=False)
while ga.describe_accelerator(AcceleratorArn=acc_arn)["Accelerator"]["Status"] != "DEPLOYED":
time.sleep(15)
for arn in groups.values():
ga.delete_endpoint_group(EndpointGroupArn=arn)
ga.delete_listener(ListenerArn=listener_arn)
ga.delete_accelerator(AcceleratorArn=acc_arn)
print(ga.list_accelerators()["Accelerators"]) # expect []
Then terminate the two instances and delete the two ALBs and their target groups in their own Regions. Confirm in Billing that no accelerator hours accrue after today. The static IPs are released when the accelerator is deleted, and you can no longer route traffic through them, so only delete when you are sure nothing has them allow listed.

