Unlike a 502 (upstream sent a bad response) or 504 (upstream never responded), a 503 usually means the proxy or application deliberately refused the request — no healthy upstream, an explicit capacity limit, or a maintenance mode.
Check target/backend health at the load balancer
aws elbv2 describe-target-health --target-group-arn TARGET_GROUP_ARNA 503 straight from an ALB with no upstream error at all usually means zero healthy targets in the group.
Check whether it's a rollout in progress
A rolling deploy that removes old pods/instances faster than new ones become ready can briefly leave zero capacity behind a load balancer — check deploy timing against when the 503s started.
kubectl rollout status deployment/DEPLOYMENT_NAMEIn Kubernetes, confirms whether a rollout is actively in progress and how far along it is.
Check for an explicit capacity or rate limit
Some proxies and application frameworks return 503 deliberately when a concurrency or queue-depth limit is hit, as a form of load shedding rather than falling over completely.
tail -n 100 /var/log/nginx/error.logLook for messages naming a specific limit (upstream connections, worker_connections) rather than a generic upstream failure.
Check readiness probes
In Kubernetes, a pod that's Running but failing readiness is excluded from Service endpoints — enough pods failing readiness at once can leave a Service with no ready backend at all, producing 503s at the ingress even though pods are technically up.
kubectl get pods -o wideCheck the READY column — 0/1 means the pod is up but not passing its readiness probe.
503 vs. 502 vs. 504
502 — the proxy got an invalid response, or the connection itself failed. 503 — the service is deliberately unavailable (no capacity, explicit limit, maintenance). 504 — the proxy connected fine but the upstream never responded within the timeout. Same symptom to a user, three different root-cause directions.