503 Service Unavailable means the server is reachable but refusing to handle requests for now. The usual reasons are maintenance mode, an overload, a hosting resource limit, or a deliberate block. Unlike a 500, nothing is necessarily broken: the server is saying “not right now”.
If you are visiting the site
A 503 is meant to be temporary. Wait a few minutes and reload. If a page says Briefly unavailable for scheduled maintenance, the site is mid-update and should return shortly.
Find the reason first
The page and the log usually say which kind of 503 it is.
| You see | Likely reason | Go to |
|---|---|---|
| Briefly unavailable for scheduled maintenance. Check back in a minute. | Stuck WordPress update | Step 1 |
| The 503 comes and goes with traffic | PHP workers or the server are overloaded | Steps 2 and 4 |
| A host-branded page, or 508 Resource Limit Is Reached | Hosting account limits | Step 3 |
| 503 for some visitors, especially bots | Rate limiting or a firewall rule | Step 5 |
| Load balancer or CDN page | No healthy server behind it | Step 6 |
If you run the site
1. Stuck WordPress maintenance mode
During updates, WordPress creates a file called .maintenance in the site folder and shows the maintenance message. If an update is interrupted, for example by a timeout or a closed browser tab, the file stays behind and every visitor sees the message. Delete it:
rm /var/www/example.com/public/.maintenance
On shared hosting, delete it with the control panel’s file manager; it is a hidden file, so turn on “show hidden files”. Then rerun the update that was interrupted, because the plugin or theme it was updating may be half-installed. With WP-CLI:
wp plugin list --update=available
wp plugin update --all
2. PHP-FPM has no free workers
Each request needs a free PHP worker. When all are busy, new requests queue, and once the queue is full they fail. Look for this warning:
sudo grep "max_children" /var/log/php*-fpm.log /var/log/php-fpm/*.log 2>/dev/null
server reached pm.max_children setting (5), consider raising it confirms it. You have three options, best first:
- Make pages cheaper: page caching serves most visitors without touching PHP at all.
- Find slow pages that hold workers for a long time (see 504 Gateway Timeout).
- Raise
pm.max_childrenin the pool file, but only as far as memory allows. Check how much each worker uses:
ps --no-headers -o rss -C php-fpm8.3 | awk '{sum+=$1; n++} END {print sum/n/1024 " MB per worker"}'
Divide the memory you can spare by that number. On RHEL-based systems the process is called php-fpm.
3. Hosting account limits
Shared and many managed hosts cap each account’s CPU, memory, processes and simultaneous connections (on CloudLinux servers these are called LVE limits). Hitting a cap returns 503 or 508. In cPanel, Resource Usage shows when and which limit was hit. Traffic spikes, bots crawling search and filter pages, and heavy plugins are the usual reasons. If real traffic has outgrown the plan, see shared, VPS, dedicated or cloud hosting.
4. Traffic floods and bots
Check the access log for one address, or one URL, being hit thousands of times:
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
sudo awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
The first lists the busiest IP addresses, the second the busiest URLs. Look up a suspicious address before blocking it, since search engine crawlers are visitors you want. Block abusive ones at the firewall, or put the site behind a CDN that filters bots.
5. Rate limits that are too strict
Nginx’s limit_req returns 503 by default when a visitor goes over the limit, which is easy to mistake for an outage. Search for it:
grep -R "limit_req" /etc/nginx/
sudo grep "limiting requests" /var/log/nginx/error.log | tail
If real visitors are being limited, raise the burst value, or set limit_req_status 429; so limited requests return 429 Too Many Requests instead, which is clearer in logs.
6. No healthy backend behind a load balancer
Load balancers return 503 when every server behind them fails its health check. Check that the health check URL returns 200 on each server, and that the backend services are running. Some setups also return 503 deliberately while an app restarts or deploys.
Tell search engines it is temporary
If you take a site down on purpose, return a real 503 with a Retry-After header rather than a normal page that says “down for maintenance”. Search engines then keep your pages indexed and come back later. A 503 that lasts more than a day or two can start to affect rankings, so keep planned downtime short.
Confirm it is fixed
curl -I https://example.com/
HTTP/2 200 means it works. If the 503 came with traffic, watch the PHP-FPM log through the next busy period to make sure the warning does not return.
Related
- 429 Too Many Requests, when a limit targets one visitor.
- 500 Internal Server Error.
- How much RAM a website needs.
Something out of date? Software changes. If a step no longer works, tell us and we will check it and update the page.



