Home / Azure

AzureTroubleshootingIntermediate

Azure App Service returns 502/503: a troubleshooting guide

Work out whether a 5xx comes from the front ends, a crashing or slow app, port binding, or exhausted outbound connections, using Diagnose and solve, logs and Kudu.

Deepak Bhardwaj3 min read

Applies toAzure App Service (Windows and Linux), App Service plans

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 or IHttpClientFactory) 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 Http5xx and HealthCheckStatus metrics.