Blog
3 min read

503 Service Unavailable: What It Means and How to Fix It

A 503 Service Unavailable means the server is temporarily unable to handle the request — overloaded, in maintenance, or with no healthy app behind it. How it differs from 500, 502 and 504, the common causes (crashed app, failed health checks, resource limits, maintenance mode) and how to fix and prevent them.

503 Service Unavailable means the server can't handle the request right now, and expects to be able to later. It's a "come back soon", not a "this is broken forever".

It's usually sent by whatever sits in front of your app — a load balancer, a reverse proxy like Nginx, a hosting platform or Cloudflare — when there's nothing healthy behind it to send your request to.

503 vs its neighbours

Code What it usually means
500 Your app ran and crashed while handling the request (500 Internal Server Error)
502 The proxy reached your app but got a bad or no response (502 Bad Gateway)
503 No healthy app available, or deliberately unavailable
504 The app took too long to answer (504 Gateway Timeout)

Common causes

1. Your app isn't running

The process crashed or never started, and the platform has nothing to route to. Check logs and process status:

systemctl status myapp
journalctl -u myapp -n 50
# or
docker ps -a && docker logs myapp --tail 50

(Docker Container Keeps Restarting)

2. Health checks are failing

Load balancers and platforms only send traffic to instances that pass a health check. If your /health endpoint is slow, returns an error, or depends on a database that's down, every instance gets marked unhealthy → 503. (Health Check Endpoints)

3. Out of memory or CPU

When a server runs out of memory, the kernel kills processes — often your app. Too few workers for the traffic also leaves requests with nowhere to go. (The Linux OOM Killer, Container CPU and Memory Limits)

4. Mid-deploy

During a restart, there's a moment with no app running. If deploys cause brief 503s, you need a zero-downtime strategy. (Zero-Downtime Deploys)

5. Rate limiting or overload protection

Some proxies (and Nginx's limit_req by default) return 503 when a client exceeds a limit, rather than 429. (Nginx Rate Limiting)

6. Maintenance mode

Some apps and platforms deliberately return 503 during maintenance. That's the correct code to use, because it tells search engines the outage is temporary.

7. An upstream service is down

If you see a 503 from a third-party API, it's on their side. Check their status page and retry with backoff. (Exponential Backoff)

Should you return 503 on purpose?

Yes, for planned maintenance. Include a Retry-After header so clients and crawlers know when to come back. Search engines treat short 503 periods as temporary and won't drop your pages; a maintenance page that returns 200 can confuse them.

Preventing 503s

  • Restart policies so a crashed app comes back automatically. (PM2 vs systemd)
  • Health checks that test the app, not every dependency.
  • Enough memory headroom, and alerts before you run out.
  • Deploys that start the new version before stopping the old one.
  • Uptime monitoring so you know first. (Know When Your App Is Down)

The summary

  • 503 = nothing healthy to serve the request right now.
  • Check whether the app is running, its health check, and memory/CPU.
  • Use 503 deliberately for maintenance, with Retry-After.

EasySpawn keeps your app running on a persistent server with automatic restarts and deploys designed to avoid gaps, and Claude Code can read the logs when something does go down. See how it works or join the waitlist.

Related: HTTP Status Codes Explained · Cloudflare 521, 522, 525 · Graceful Shutdown in Node.js · What Does 99.9% Uptime Mean?

Keep reading