Cloud
Azure Front Door: qualify origin health before failing over
A production runbook for qualifying Azure Front Door origin health with probes, routing, DNS, TLS, WAF evidence, backend logs, validation and rollback before forcing failover.
When Azure Front Door marks an origin unhealthy, the fastest reaction is often to force traffic to another region, disable the failing origin or relax WAF rules until the application answers again. That can restore service. It can also hide the real boundary: a probe path that no longer exists, an origin certificate mismatch, DNS drift, backend throttling, a WAF false positive, or a deployment that only breaks one route.
The use case is an external application published through Azure Front Door on app.example.com. The active origin group points to app-west.example.net and app-north.example.net. After a release, users receive intermittent 503 responses and Front Door health shows the west origin as degraded. The runbook goal is to decide whether to fail over, fix the origin, adjust the probe, rollback the release, or keep traffic split while collecting evidence.
Freeze the traffic contract
Start by writing the route as it is supposed to work. Front Door is not only a global entry point. It is a contract between hostname, route, origin group, health probe, WAF policy, TLS expectations and backend readiness.
front_door:
profile: afd-prod-global
endpoint: afd-app-prod
hostname: app.example.com
route: app-main
origin_group: og-app-prod
origins:
- name: app-west
host: app-west.example.net
region: westeurope
priority: 1
weight: 1000
- name: app-north
host: app-north.example.net
region: northeurope
priority: 2
weight: 1000
probe_contract:
path: /health/ready
protocol: HTTPS
expected_status: 200
host_header: app.example.com
rollback_reference:
last_known_good_route: app-main@2026-07-21T09:00Z
last_known_good_release: app-api-20260721.3 If this contract is unknown, the first action is discovery, not failover. Otherwise the team may move traffic away from a healthy origin because the probe itself is wrong.
Separate user path, probe path and backend path
A failing health probe does not always mean the user path is down. A healthy probe does not always mean the application path is usable. Check the three paths separately.
User path
Host: app.example.com
Path: /checkout/confirm
Purpose: prove user impact through Front Door and WAF
Probe path
Host header: app.example.com
Path: /health/ready
Purpose: decide whether Front Door should keep the origin in rotation
Backend path
Host: app-west.example.net or internal backend hostname
Path: /health/ready and one real application route
Purpose: prove whether the origin itself is reachable and ready
Interpretation
User path fails, probe path succeeds: suspect WAF, route, cache, application route or dependency
Probe path fails, backend path succeeds: suspect host header, probe config, TLS or probe endpoint
Backend path fails directly: suspect deployment, origin service, dependency, DNS or certificate
Only one region fails: keep failover possible but prove regional difference first This split prevents a common mistake: treating Front Door health as the only source of truth during an application incident.
Read Front Door evidence first
Use logs to check whether Front Door sees origin failures, WAF blocks, routing changes or only user-facing errors. Keep a narrow time window around the first degraded signal.
let StartTime = datetime(2026-07-21T09:10:00Z);
let EndTime = datetime(2026-07-21T09:40:00Z);
AzureDiagnostics
| where TimeGenerated between (StartTime .. EndTime)
| where ResourceProvider == "MICROSOFT.CDN"
| where Category in ("FrontDoorAccessLog", "FrontDoorHealthProbeLog", "FrontDoorWebApplicationFirewallLog")
| extend host = tostring(requestUri_s)
| extend origin = coalesce(tostring(originName_s), tostring(BackendHostname_s))
| summarize requests=count(),
failures=countif(toint(httpStatusCode_s) >= 500),
wafBlocks=countif(action_s in ("Block", "Blocked")),
sampleStatus=make_set(httpStatusCode_s, 8),
sampleRules=make_set(ruleName_s, 8)
by Category, origin, bin(TimeGenerated, 5m)
| order by TimeGenerated asc Adapt table and field names to your diagnostic settings. The useful question is not only “is the origin unhealthy?” but “which layer produced the first evidence?”
Validate DNS and TLS before moving traffic
Origin health depends on the exact hostname, certificate and host header seen from the Front Door path. A certificate rotation, DNS update or origin hostname change can break probes without breaking a direct internal test.
FRONTDOOR_HOST="app.example.com"
ORIGIN_HOST="app-west.example.net"
PROBE_PATH="/health/ready"
dig +short "$FRONTDOOR_HOST"
dig +short "$ORIGIN_HOST"
curl -I "https://$FRONTDOOR_HOST$PROBE_PATH" -H "x-correlation-id: afd-probe-check-20260721"
curl -I "https://$ORIGIN_HOST$PROBE_PATH" -H "Host: $FRONTDOOR_HOST" -H "x-correlation-id: origin-direct-check-20260721"
openssl s_client -connect "$ORIGIN_HOST:443" -servername "$FRONTDOOR_HOST" </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates If direct origin checks only pass with a different host header, fix the route or origin contract before forcing global failover.
Check origin group state and recent changes
Before changing weights or priorities, capture the current origin group state and the latest deployment or infrastructure change.
RESOURCE_GROUP="rg-edge-prod"
PROFILE="afd-prod-global"
ORIGIN_GROUP="og-app-prod"
az afd origin list --resource-group "$RESOURCE_GROUP" --profile-name "$PROFILE" --origin-group-name "$ORIGIN_GROUP" --query "[].{name:name,hostName:hostName,enabled:enabledState,priority:priority,weight:weight,originHostHeader:originHostHeader}" --output table
az afd origin-group show --resource-group "$RESOURCE_GROUP" --profile-name "$PROFILE" --origin-group-name "$ORIGIN_GROUP" --query "{name:name,probePath:healthProbeSettings.probePath,probeProtocol:healthProbeSettings.probeProtocol,probeRequestType:healthProbeSettings.probeRequestType,loadBalancing:loadBalancingSettings}" The output should go into the incident note before any failover. It is the rollback target if the team changes weights, disables an origin or edits the probe.
Correlate backend logs with the same request
Front Door can prove that it sent or blocked a request. The backend must prove whether it received it, which instance handled it and which dependency failed.
let CorrelationId = "origin-direct-check-20260721";
AppRequests
| where TimeGenerated > ago(2h)
| where tostring(Properties["x-correlation-id"]) == CorrelationId
| project TimeGenerated,
AppRoleName,
OperationName,
Url,
ResultCode,
Success,
DurationMs,
CloudRoleInstance,
DependencyFailure = tostring(Properties["dependency_failure"])
| order by TimeGenerated asc If the backend never sees the request, stay on DNS, TLS, WAF, route and origin reachability. If the backend sees the request and returns errors, failover may be a workaround, but the release or dependency still needs a decision.
Decide failover, fix, rollback or hold
Make the decision explicit. A global failover is a production change, not just a traffic trick.
Fail over now
User-impacting route fails through the active origin
Secondary origin is validated through the same hostname and path
WAF and route rules are not the primary cause
Backend evidence shows regional origin failure or bad release in one region
Rollback to previous weights or priority is documented
Fix origin or probe first
Probe path fails but user path is healthy
Direct origin check succeeds only with different host header
TLS certificate does not match the expected SNI
Probe endpoint changed during release
Origin health does not match backend readiness evidence
Rollback release
Front Door routing is stable
Both probe and real application path reach the origin
Backend logs show errors after the new deployment
Previous release is known and can be restored safely
Hold traffic split
Impact is intermittent and secondary capacity is not proven
Evidence differs between WAF, probe and backend logs
A forced failover could move users to an unvalidated path This decision table keeps the team from using failover as a diagnostic shortcut.
Validate after the change
After failover, probe fix or rollback, validate the same chain again. The incident is not closed when traffic moves. It is closed when the route is explainable and reversible.
Validation after action
Front Door route returns expected status for one real user path
Health probe status matches backend readiness
WAF logs show expected allow or block behavior
Backend logs contain the correlation ID on the selected origin
Error rate does not move to the secondary origin
Origin weights, priorities and probe settings match the incident note
Rollback command or configuration version remains available
Rollback trigger
Secondary origin returns the same error
WAF starts blocking a wider path
Probe becomes healthy but user path still fails
Backend logs show dependency failure unrelated to region If validation fails, revert the traffic change or keep the degraded origin out of rotation only with an explicit owner and expiry.
Conclusion
Azure Front Door failover should be driven by evidence, not by a red health indicator alone. Separate user path, probe path, origin DNS, TLS, WAF, routing and backend logs before moving global traffic.
The safe decision may be failover, but it may also be a probe correction, a certificate fix, a release rollback or a temporary hold while the secondary path is validated. The operational value is the same in every case: the team knows what changed, why it changed, and how to return to the previous state.