What the codes usually mean
| Code | Usual cause on App Service |
|---|---|
| 502.3 / 502 | The app didn't respond in time or crashed mid-request. On Linux, the container isn't listening on the expected port. |
| 503 | The app is stopped, restarting, or out of workers/memory. Can also mean the plan is overloaded. |
| 504 / 230-second timeout | The request ran longer than the front end's ~230 s limit |
| 500.x | An unhandled exception in your code. Read the app logs. |
1. Start with "Diagnose and solve problems"
In the portal, open Diagnose and solve problems → Availability and Performance. It correlates restarts, CPU and memory, the HTTP 5xx breakdown and platform events. That's often enough to find the cause in two minutes.
2. Is the app restarting?
az webapp log tail -g rg-web -n app-prod # live stream (enable logging first)
az webapp show -g rg-web -n app-prod --query "{state:state, plan:appServicePlanId}" -o table
// With diagnostic settings sending to Log Analytics
AppServiceConsoleLogs
| where TimeGenerated > ago(1h)
| where ResultDescription has_any ("exception", "error", "exited", "OOM")
| project TimeGenerated, ResultDescription
| order by TimeGenerated desc
AppServiceHTTPLogs
| where TimeGenerated > ago(1h) and ScStatus >= 500
| summarize count() by ScStatus, CsUriStem
| top 20 by count_
3. Linux containers: the port
The container must listen on the port App Service sends traffic to. That's 80 by default, or whatever WEBSITES_PORT is set to.
az webapp config appsettings list -g rg-web -n app-prod --query "[?name=='WEBSITES_PORT']"
az webapp config appsettings set -g rg-web -n app-prod --settings WEBSITES_PORT=8080
If the log shows Container didn't respond to HTTP pings on port, either the port is wrong or the app takes longer to start than the start-up limit. Raise the limit with WEBSITES_CONTAINER_START_TIME_LIMIT (seconds).
4. Memory and CPU on the plan
Every app in a plan shares its instances. A memory-hungry neighbour can starve your app.
- Check App Service plan → Metrics → Memory Percentage / CPU Percentage.
- Above about 85% sustained, scale up (bigger SKU) or out (more instances), or move noisy apps to their own plan.
5. Outbound connection exhaustion (SNAT)
Apps that open a new HTTP or SQL connection per request run out of SNAT ports. You'll see intermittent 5xx errors and connection timeouts to downstream services.
- Diagnose: Diagnose and solve → SNAT Port Exhaustion.
- Fix in code: reuse
HttpClient(a single instance orIHttpClientFactory) and use connection pooling. - Fix in infrastructure: VNet integration with a NAT gateway gives you far more ports.
6. Long requests (230 s limit)
The front ends close requests after about 230 seconds. That limit can't be raised. Move long work to a background job (WebJobs, Functions, a queue) and return 202 Accepted with a status URL.
Quick recovery while you investigate
az webapp restart -g rg-web -n app-prod
Restarting clears memory leaks and stuck threads, but take a memory dump first (Diagnose and solve → Collect Memory Dump), or the evidence is gone.
Prevent it next time
- Turn on Health check (
/health) so unhealthy instances are taken out of rotation automatically. - Run at least 2 instances for production plans.
- Alert on
Http5xxandHealthCheckStatusmetrics.