503 Service Unavailable Error: Causes and How to Fix It

By 

•

Updated on

•

11 min read

503 Service Unavailable Error

The 503 Service Unavailable error appears when a server cannot process a request. Unlike client-side errors such as 404, a 503 is always a server-side problem: the server is either overloaded, under maintenance, or a backend service it depends on has stopped responding.

If you are a visitor, there is little you can do except wait or try again later. If you manage the server, this guide walks through the most common causes and how to diagnose and resolve the error.

Quick Reference

CauseWhere to Look
Backend application down (Apache proxy)AH00957 or AH01114 in /var/log/apache2/error.log
PHP-FPM stopped (Apache)sudo systemctl status php8.5-fpm, AH02454 in the Apache error log
Nginx rate limitinglimiting requests in /var/log/nginx/error.log
Maintenance modereturn 503 in the Nginx config, .maintenance file in WordPress
No healthy servers behind HAProxyBackend health checks, No server is available to handle this request
Server overload or OOM killfree -h, sudo journalctl -k
Application returns its own 503Application logs

What Is an HTTP 503 Error

When you open a web page, your browser sends a request to the server hosting the site, which returns the requested data and a response code. The HTTP response status code tells the client whether the request has been successful or not.

Response codes are categorized into five classes. The codes in the range of 500 to 599 indicate a server error.

The HTTP status code 503 is a generic error response returned when the server cannot handle the request. There are many reasons why a server is not ready to complete the request and return a 503 error. This error code usually appears when the server is overloaded with requests or down for maintenance. Nginx labels the same code 503 Service Temporarily Unavailable. That is the text you will see on its default error page.

Error 503

The neighboring 5xx codes describe different failures. A 500 error means the server hit an unexpected condition while processing the request. A 502 Bad Gateway means a proxy could not get a valid response from the upstream server. A 504 Gateway Timeout means the upstream server was reached but did not answer in time. A 503 says the service is temporarily unable to take the request at all.

What Visitors Can Do

If the page you are visiting shows a 503 error, there is not much you can do, since the error is not caused by your browser or internet connection. Even though the error is on the server side, you can try some of the following options:

  • Reload your browser or try opening the page with another one. The chances that the page will load when you refresh your browser are low, but it is worth trying.
  • Try to clear your browser cache. If the page showing a 503 error is cached, the browser will request a new version after the cache is cleared.
  • Come back later. The web admin may fix the web server issue in the meantime.
  • Contact the website owners. The last remaining option is to contact the person responsible for maintaining the website.

Common Causes

Several different reasons can cause a 503 Service Unavailable error on the server side. The most common are:

  • Server overload. When traffic spikes beyond capacity, the server stops accepting new requests.
  • Scheduled maintenance. The server or an application on it may be in maintenance mode. WordPress, for example, returns 503 while applying automatic updates.
  • Backend service not running. If Apache is configured as a reverse proxy and the backend application (Node.js, Gunicorn, PHP-FPM) has crashed, Apache returns 503 for every request. Nginx reports the same failure as a 502 Bad Gateway.
  • Rate limiting. Nginx rejects requests over the limit_req or limit_conn limit with a 503 by default.
  • No available servers behind a load balancer. HAProxy and AWS Classic Load Balancers return 503 when no backend server is healthy. AWS Application Load Balancers handle failed health checks differently, as explained below.
  • DDoS or traffic flood. A flood of requests exhausts server resources and produces the same result as organic overload.
  • Broken plugin or hacked site. Malicious code or a broken CMS plugin can crash a process and trigger 503 errors.

The sections below show how to confirm each of these on the server.

Checking the Web Server Status

Start by confirming the web server is running. On Ubuntu and Debian:

Terminal
sudo systemctl status nginx
Terminal
sudo systemctl status apache2

If the service is stopped or in a failed state, restart it:

Terminal
sudo systemctl restart nginx
Terminal
sudo systemctl restart apache2

For more on managing services, see our guide on the systemctl command .

Reading the Error Logs

The error log is the most direct way to identify the cause. Tail the last 50 lines:

Terminal
sudo tail -n 50 /var/log/nginx/error.log
Terminal
sudo tail -n 50 /var/log/apache2/error.log

On Fedora, RHEL, and derivatives, the Apache log is at /var/log/httpd/error_log.

When Apache cannot reach a proxied backend, the log records the failed connection and the backend address:

output
[proxy:error] [pid 17698:tid 17714] (111)Connection refused: AH00957: http: attempt to connect to 127.0.0.1:3000 (127.0.0.1:3000) failed
[proxy_http:error] [pid 17698:tid 17714] [client ::1:55892] AH01114: HTTP: failed to make connection to backend: 127.0.0.1

The (111)Connection refused part tells you nothing is listening on 127.0.0.1:3000. The second line confirms that Apache gave up on the backend and answered the client with a 503.

If a service writes to the systemd journal instead of a file, read its recent entries with journalctl:

Terminal
sudo journalctl -u nginx -n 50

Our guides on the Nginx log files and the Apache log files explain how to change the log location and severity level.

Checking PHP-FPM

On PHP sites served by Apache, a stopped PHP-FPM service is one of the most frequent causes of 503 errors. Check its status:

Terminal
sudo systemctl status php8.5-fpm

Replace php8.5-fpm with your installed version. Ubuntu 26.04 ships PHP 8.5, and Ubuntu 24.04 ships PHP 8.3. If the service is stopped, the Apache error log shows that it could not reach the socket:

output
[proxy:error] [pid 17699:tid 17702] (2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php/php8.5-fpm.sock (localhost:8000) failed

Restart the service and check its log for errors:

Terminal
sudo systemctl restart php8.5-fpm
sudo tail -n 50 /var/log/php8.5-fpm.log

Nginx handles the same situation differently. When PHP-FPM is stopped, Nginx returns a 502 Bad Gateway, not a 503.

Reaching a PHP-FPM pool’s pm.max_children limit does not itself generate a 503. Extra requests normally wait in the listen queue until a worker is free, but the queue has a maximum size set by listen.backlog. If the queue fills or a request times out, the web server can return a proxy error.

Checking the Upstream Backend

If Apache or Nginx is acting as a reverse proxy in front of a Node.js, Python, or Ruby application, check whether the backend port is listening:

Terminal
sudo ss -tlnp | grep 3000

Replace 3000 with the port your application uses. Without sudo, ss does not show the process name for sockets owned by other users. If nothing is listening on that port, the backend has stopped and needs to be restarted. See our ss command guide for more options.

Once the backend is running again, Apache normally resumes forwarding requests without a restart. If the proxy worker was marked in error, Apache may wait for its retry interval before trying the backend again. The default interval is 60 seconds.

Checking SELinux

On Fedora and RHEL, SELinux can block Apache from opening network connections even when the backend is running. The Apache error log shows (13)Permission denied next to the failed connection. If SELinux is denying Apache’s outbound connection, allow it with:

Terminal
sudo setsebool -P httpd_can_network_connect on

Rate Limiting in Nginx

Nginx returns a 503 when a client exceeds a limit set with the limit_req or limit_conn directive. The site works for most visitors, but some requests fail. This often happens under bursty traffic or with clients behind a shared IP address.

Each rejected request leaves an entry in the Nginx error log:

output
2026/10/03 18:17:28 [error] 17657#17657: *9 limiting requests, excess: 1.000 by zone "one", client: 127.0.0.1, server: , request: "GET /limited/index.nginx-debian.html HTTP/1.1", host: "localhost"

The zone "one" part names the limit_req_zone that rejected the request, and client shows the address that hit the limit. If legitimate visitors trip the limit, raise the rate or add a burst value to the limit_req line.

Rate limiting is not a server failure, so a 503 can be misleading here. You can change the status code to 429 Too Many Requests in the same http, server, or location block:

nginx
limit_req_status 429;

The limit_conn_status directive does the same for connection limits. Test the configuration with sudo nginx -t and reload Nginx to apply the change.

Maintenance Mode and Retry-After

A 503 is the correct response while a site is down for planned work. Search engines treat it as a temporary state and come back later. A 200 maintenance page or a 404 can replace the indexed content. Keep the window short, though. A site that returns 503 for days can still lose pages from the index.

To put a site into maintenance mode in Nginx, return a 503 and add a Retry-After header with the number of seconds until the site is expected back:

nginx
location / {
    add_header Retry-After 3600 always;
    return 503;
}

Without always, Nginx omits the header from a 503 response. You can confirm the result with curl :

Terminal
curl -i http://localhost/
output
HTTP/1.1 503 Service Temporarily Unavailable
Server: nginx/1.28.3 (Ubuntu)
Date: Sat, 03 Oct 2026 18:17:15 GMT
Content-Type: text/html
Content-Length: 206
Connection: keep-alive
Retry-After: 3600

The status line shows the 503, and Retry-After: 3600 tells clients to try again in one hour.

WordPress enters maintenance mode on its own while it installs updates. It creates a .maintenance file in the site root and returns a 503 with the message “Briefly unavailable for scheduled maintenance. Check back in a minute.” WordPress ignores the file once its $upgrading timestamp is at least ten minutes old.

If an update is interrupted, the file can be left behind and keep the site in maintenance mode until that timestamp expires. After confirming that no update is running, remove the leftover file:

Terminal
sudo rm /var/www/html/.maintenance

Replace /var/www/html with the path to your WordPress installation. After the site loads, check that the interrupted plugin or theme update completed.

Load Balancers and Proxies

When a load balancer sits in front of your web servers, the 503 may come from the load balancer and not from the web server. HAProxy returns this page when every server in the backend is marked down:

output
HTTP/1.0 503 Service Unavailable
cache-control: no-cache
content-type: text/html

<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>

The text “No server is available to handle this request” comes from HAProxy itself. Check that the backend servers are running and that the health check defined with the check option can reach them. If the web servers are fine but the health check path returns an error, HAProxy still marks them down.

On AWS, a Classic Load Balancer can return 503 when it has no registered instances, no healthy instances, insufficient load balancer capacity, or a full surge queue. Check registered instance health in the load balancer console and the HealthyHostCount and SpilloverCount metrics in CloudWatch. Classic Load Balancers do not use target groups.

An Application Load Balancer behaves differently. If all registered targets fail their health checks, it normally routes requests to those unhealthy targets, a behavior called fail-open. It returns 503 when the target group has no registered targets or all registered targets are in the unused state. Check the target group attached to the matching listener rule and each target’s status. The AWS troubleshooting guide lists other 503 causes, including requests rejected when target optimizer is enabled and no targets are ready.

Server Overload

A server that runs out of memory or CPU stops answering requests in time. Check the available memory with the free command :

Terminal
free -h

If the available column is close to zero, the kernel may have killed the web server or application worker to free memory. Our guide on diagnosing OOM killer events shows how to confirm this from the kernel log.

For persistent overload, add caching, scale the server, or put rate limiting in front of the expensive endpoints.

Conclusion

The 503 Service Unavailable error points to the server, not the visitor. In most cases, the web server error log names the backend, rate limit, or load balancer behind it. If the error turns out to be a 500 instead, see our guide on the 500 Internal Server Error .

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page