Symptom
Origin servers scale out under traffic that's mostly the same images, scripts and pages. Users far from the origin region see slow page loads. Front Door egress and origin costs both grow.
1. Measure today
Front Door metrics: Byte Hit Ratio, Request Count split by cache status, Origin Request Count, Total Latency and Origin Latency.
With access logs in Log Analytics:
AzureDiagnostics
| where Category == "FrontDoorAccessLog" and TimeGenerated > ago(1d)
| summarize requests = count() by cacheStatus_s
| extend pct = round(100.0 * requests / toscalar(
AzureDiagnostics | where Category == "FrontDoorAccessLog" and TimeGenerated > ago(1d) | count), 1)
AzureDiagnostics
| where Category == "FrontDoorAccessLog" and TimeGenerated > ago(1d) and cacheStatus_s in ("MISS", "CONFIG_NOCACHE")
| summarize requests = count() by path = tostring(split(requestUri_s, "?")[0])
| top 25 by requests
(With resource-specific logs, the table is AFDAccessLog / similar with typed columns.)
2. Decide what's cacheable
| Content | Cache? | Typical TTL |
|---|---|---|
Versioned static assets (app.3f9c1.js, images with hash) | Yes | Long (days to a year) |
| Unversioned static assets | Yes | Short (minutes to hours) |
| Public pages, same for everyone | Often | Short, with purge on publish |
| Personalised pages, APIs with auth | No | n/a |
| API responses identical for all users (reference data) | Sometimes | Short |
3. Set headers at the origin
The cleanest control is Cache-Control from the app:
Cache-Control: public, max-age=31536000, immutable # hashed assets
Cache-Control: public, max-age=300 # public pages
Cache-Control: private, no-store # personalised / authenticated
Front Door honours origin cache headers when caching is enabled on the route (unless you override them with rules).
4. Enable caching and compression on routes
az afd route update -g rg-edge --profile-name afd-prod --endpoint-name web --route-name static \
--enable-caching true --query-string-caching-behavior IgnoreQueryString \
--enable-compression true \
--content-types-to-compress text/html text/css application/javascript application/json image/svg+xml
Query string behaviour:
| Setting | Use when |
|---|---|
| IgnoreQueryString | Query strings don't change the content (tracking params) |
| UseQueryString | Every distinct query is distinct content |
| IgnoreSpecifiedQueryStrings / IncludeSpecifiedQueryStrings | Only some parameters matter. Best for keeping hit ratio high |
Compression applies to files within the documented size range and when the client accepts it. If the origin already compresses, Front Door passes that through.
5. Rule sets for exceptions
Use rule sets to:
- Override caching for paths like
/api/*(no cache) or/static/*(cache, long TTL). - Add
Cache-Controlwhen an origin you can't change sends nothing useful. - Remove
Set-Cookiefrom static responses (cookies can stop caching).
6. Purge without hurting the origin
az afd endpoint purge -g rg-edge --profile-name afd-prod --endpoint-name web --content-paths "/css/*" "/index.html"
Purge narrow paths after deployments; avoid /* at peak time, which sends a wave of misses to the origin. Hashed file names make most purges unnecessary.
7. Measure again
Target examples: byte hit ratio for static routes > 90%, origin request count down, page load time down in far regions. Then reconsider origin scale (fewer instances may now be enough).
Warning
Caching an authenticated or personalised response can show one user's data to another. Make sure authenticated paths send
private/no-storeand that the route or rule set doesn't override them.
Checklist
- Hit ratio and top MISS paths measured
- Cacheable content classified
- Origin sends correct Cache-Control
- Caching, query string behaviour and compression set per route
- Rule sets for exceptions; no caching of personal data
- Targeted purges in the deployment pipeline