Serve global traffic from the Azure edge with Front Door, cache static content, and route users to the nearest healthy region.

Bishal Biswas
Self Learner
What Front Door is
Front Door is a global entry point. A request from anywhere in the world hits the nearest Microsoft edge location, and travels to your origin over Microsoft’s backbone rather than the public internet.
Without user in Sydney -> public internet -> your app in London
With user in Sydney -> Sydney edge -> Microsoft backbone -> London
That alone reduces latency noticeably, because the backbone is faster and more consistent than the open internet.
It also does caching, TLS termination at the edge, WAF, and failover between regions.
Azure CDN is gone
Azure CDN Standard from Microsoft (classic) was retired on 30 September 2025, and the Edgio profiles were retired earlier in January 2025 after Edgio’s bankruptcy.
Front Door is the replacement. Anything still on a classic CDN profile needs migrating, and Microsoft provides a migration path in the portal.
Front Door Standard and Premium include CDN capability, so there is no separate product to choose any more.
Standard or Premium
Standard routing, caching, custom domains, basic rules
Premium adds managed WAF rule sets, bot protection, Private Link to origins
Premium’s Private Link support matters: it lets Front Door reach an origin that has no public endpoint at all, which is the cleanest way to make an origin unreachable except through the edge.
az afd profile create \
--profile-name afd-shop --resource-group rg-shop-global \
--sku Premium_AzureFrontDoor
The pieces
Profile the top level resource
Endpoint a hostname, like shop-abc123.z01.azurefd.net
Origin group a set of origins with health probes and load balancing
Origin one backend: App Service, Storage, a public IP, anything
Route maps patterns on an endpoint to an origin group
Rule set transformations applied per request
az afd endpoint create \
--profile-name afd-shop --resource-group rg-shop-global \
--endpoint-name shop --enabled-state Enabled
az afd origin-group create \
--profile-name afd-shop --resource-group rg-shop-global \
--origin-group-name og-shop \
--probe-request-type GET --probe-protocol Https \
--probe-path /healthz --probe-interval-in-seconds 30 \
--sample-size 4 --successful-samples-required 3 \
--additional-latency-in-milliseconds 50
az afd origin create \
--profile-name afd-shop --resource-group rg-shop-global \
--origin-group-name og-shop --origin-name uks \
--host-name shop-uks.azurewebsites.net \
--origin-host-header shop-uks.azurewebsites.net \
--priority 1 --weight 1000 --enabled-state Enabled --https-port 443
az afd route create \
--profile-name afd-shop --resource-group rg-shop-global \
--endpoint-name shop --route-name default \
--origin-group og-shop --supported-protocols Https \
--patterns-to-match "/*" --forwarding-protocol HttpsOnly \
--https-redirect Enabled
Multi region routing
Add a second origin, and priority decides the behaviour.
az afd origin create \
--profile-name afd-shop --resource-group rg-shop-global \
--origin-group-name og-shop --origin-name ne \
--host-name shop-ne.azurewebsites.net \
--priority 2 --weight 1000 --enabled-state Enabled --https-port 443
Same priority traffic goes to the lowest latency healthy origin
Different priority priority 1 is active, priority 2 is standby
Same priority gives active active with latency based routing. Different priorities give active passive failover, where the second region takes over only when the first fails its probe.
--additional-latency-in-milliseconds sets how much slower an origin may be and still be considered equivalent. Set to 50, origins within 50ms of the fastest all receive traffic.
Health probes
--probe-path point at a real health endpoint, not /
--probe-interval-in-seconds how often
--sample-size how many samples are considered
--successful-samples-required how many must pass
A probe on / often returns 200 from a web server whose database is down. A /healthz that actually checks dependencies gives failover that works.
Do not make the health endpoint expensive. Probes come from every edge location, so a heavy check runs constantly.
Caching
az afd route update \
--profile-name afd-shop --resource-group rg-shop-global \
--endpoint-name shop --route-name static \
--enable-caching true \
--query-string-caching-behavior IgnoreQueryString \
--content-types-to-compress text/html text/css application/javascript application/json
IgnoreQueryString one cached copy regardless of query. Fast, and wrong for search.
UseQueryString each distinct query is cached separately
IgnoreSpecifiedQueryStrings ignore tracking parameters only
The last one is usually right. Tracking parameters like utm_source should not fragment the cache, but a real parameter like ?page=2 should.
Origin Cache-Control headers are respected, and that is the better place to control caching because the rule lives with the content.
az afd endpoint purge \
--profile-name afd-shop --resource-group rg-shop-global \
--endpoint-name shop --content-paths "/index.html" "/css/*"
Purging is for emergencies. Content addressed file names, like app.a3f9c2.js, make purging unnecessary, and that is the pattern to aim for.
Custom domains
az afd custom-domain create \
--profile-name afd-shop --resource-group rg-shop-global \
--custom-domain-name shop-example-com \
--host-name shop.example.com \
--minimum-tls-version TLS12 \
--certificate-type ManagedCertificate
Managed certificates are issued and renewed by Azure at no cost. Use them unless you need a specific certificate authority.
Validation needs a DNS TXT record, then the domain itself points at the endpoint with CNAME. For an apex domain, Azure DNS alias records work where CNAME is not allowed.
Locking the origin down
Front Door in front of a publicly reachable origin means the origin can still be hit directly, bypassing WAF and caching. Close that.
Every Front Door request carries X-Azure-FDID with your profile’s identifier. Restrict the origin to the AzureFrontDoor.Backend service tag and check that header:
az webapp config access-restriction add \
--name shop-uks --resource-group rg-shop-prod-uks \
--rule-name allow-front-door --priority 100 --action Allow \
--service-tag AzureFrontDoor.Backend \
--http-header x-azure-fdid=YOUR_FRONT_DOOR_ID
The service tag alone is not enough, because it covers everyone’s Front Door. The header is what makes it yours. This is a real and commonly missed exposure.
With Premium and Private Link, the origin needs no public endpoint at all, which is better still.
Rules engine
Redirect http to https
Add security headers
Rewrite a path before forwarding
Route mobile user agents differently
Override cache duration for one path
Rules run at the edge, so they cost nothing at the origin. Security headers applied here cover every origin at once.
Front Door or Traffic Manager
Front Door carries traffic, HTTP only, caches, WAF, fast failover
Traffic Manager DNS only, any protocol, failover limited by DNS TTL
Traffic Manager only answers DNS queries, so failover waits for client caches to expire. Front Door fails over in seconds because it is in the path.
Traffic Manager still fits non HTTP protocols, and it is cheap.
Quick recap
- Front Door puts your app on Microsoft’s backbone from the nearest edge.
- Azure CDN classic profiles were retired in 2025, and Front Door is the replacement.
- Equal origin priorities give latency based active active, different priorities give failover.
- Point health probes at a real dependency check, and keep it cheap.
- Ignore tracking query parameters rather than all of them, or search breaks.
- Restrict the origin with both the service tag and the
X-Azure-FDIDheader, since the tag alone covers everyone’s Front Door. - Traffic Manager is DNS only, so its failover is as slow as the TTL.
# Front Door is a GLOBAL entry point: the request hits the nearest Microsoft
# edge and travels to your origin over MICROSOFT'S BACKBONE, not the public
# internet. Lower and far more consistent latency.
# AZURE CDN CLASSIC WAS RETIRED 30 September 2025 (Edgio profiles earlier,
# in January 2025). FRONT DOOR IS THE REPLACEMENT, and includes CDN.
# Standard routing, caching, custom domains, rules
# Premium adds managed WAF, bot protection, PRIVATE LINK to origins
az afd profile create --profile-name afd-shop --resource-group rg-shop-global \
--sku Premium_AzureFrontDoor
# PIECES: profile -> endpoint -> origin group -> origins, joined by a route.
az afd origin-group create --profile-name afd-shop --resource-group rg-shop-global \
--origin-group-name og-shop --probe-request-type GET --probe-protocol Https \
--probe-path /healthz --probe-interval-in-seconds 30 \
--sample-size 4 --successful-samples-required 3 \
--additional-latency-in-milliseconds 50
az afd origin create --profile-name afd-shop --resource-group rg-shop-global \
--origin-group-name og-shop --origin-name uks \
--host-name shop-uks.azurewebsites.net --priority 1 --weight 1000 --https-port 443
# PRIORITY DECIDES THE BEHAVIOUR:
# same priority active active, lowest latency healthy origin wins
# different priority active passive, 2 takes over when 1 fails its probe
# PROBE A REAL HEALTH ENDPOINT, not /. A web server whose database is down
# still returns 200 from /. Keep it cheap: every edge probes constantly.
# CACHING. Ignore TRACKING parameters, not all of them, or search breaks:
# IgnoreQueryString one copy regardless of query. Wrong for search.
# UseQueryString each query cached separately
# IgnoreSpecifiedQueryStrings ignore utm_source and friends only <- usually right
az afd route update --profile-name afd-shop --resource-group rg-shop-global \
--endpoint-name shop --route-name static --enable-caching true \
--query-string-caching-behavior IgnoreQueryString
# Purging is for emergencies. Content addressed names (app.a3f9c2.js) make
# it unnecessary, and that is the pattern to aim for.
# LOCK THE ORIGIN DOWN, or it can be hit directly, bypassing WAF and cache.
# THE SERVICE TAG ALONE IS NOT ENOUGH: it covers EVERYONE'S Front Door.
# The X-Azure-FDID header is what makes it yours. Commonly missed.
az webapp config access-restriction add --name shop-uks \
--resource-group rg-shop-prod-uks --rule-name allow-front-door \
--priority 100 --action Allow --service-tag AzureFrontDoor.Backend \
--http-header x-azure-fdid=YOUR_FRONT_DOOR_ID
# FRONT DOOR vs TRAFFIC MANAGER: Traffic Manager only answers DNS, so
# failover waits for client caches to expire. Front Door is IN THE PATH and
# fails over in seconds. Traffic Manager still fits non HTTP protocols.
Was this explanation helpful?
Your feedback helps us improve the content for everyone.
Thank you for your feedback!
We appreciate you helping us improve.
What could we improve? (Optional)
Read aloud
Ready