HTTP 500, 502, 503: what each code actually means
When a site breaks, the reflex is to open the code. The error code on screen is a faster clue: it tells you which layer failed, and the three most common ones point to three completely different repairs. Five minutes of reading here saves an hour of looking in the wrong place.
The three codes, in one table
| Code | Who emits it | Most frequent cause | Look at first |
|---|---|---|---|
| 500 | Your application | Fatal error, database stopped, full disk | The application log |
| 502 | The proxy in front | The process behind it died | The state of PHP-FPM or the service |
| 503 | The server, deliberately | Maintenance or saturation | The maintenance flag, then the load |
| 504 | The proxy in front | The service behind is too slow | A blocking query, a third-party service |
The 504 is not in the title and yet it accompanies the others so often that it deserves its row: it is the only one of the four indicating slowness rather than a stop.
500: the application crashed
The server is alive and answered. Your code did not finish.
The three causes that come up most:
- A fatal error after a deployment: a missing dependency, a different language version, an absent config file.
- The database is not answering: service stopped, connections exhausted, password changed and not propagated.
- The disk is full. The most underestimated cause, because it looks like nothing: sessions stop being written, logs too, and the application falls over incoherent errors.
Where to look: your application log, in the minute the error appeared. A 500 almost always leaves a trace with a file and a line number.
502: the machine in front got a bad answer
A 502 comes from a proxy: Nginx, a load balancer, a CDN. It forwarded your visitor's request to the server behind it, and got back something it could not use, or nothing at all.
The three usual causes:
- The process behind died or was never started: PHP-FPM down, a Node service that crashed, a container that failed to restart after a deployment.
- The communication path is wrong: a renamed socket, a changed port, an internal address that moved during an update.
- The process was killed for lack of memory. The system log says so, the application does not.
Where to look: the state of the service behind the proxy, before the code.
503: the server refuses, temporarily
A 503 is a deliberate answer: not now. Either the site is in maintenance mode, or the server is out of capacity and rejects rather than collapses.
It is the most reassuring of the three: nothing is broken. It is also the one
that lasts longest, because it usually follows a traffic spike or a queue that is
not draining. And it is the only one that can be the correct answer: during
announced maintenance, a 503 with a Retry-After header is exactly what should
be returned.
Where to look: whether a maintenance flag is still enabled, then the load. A maintenance mode forgotten after a Friday deployment is an absolute classic.
Where to read the log, by stack
tail -n 100 /var/log/nginx/error.log # Nginx, including 502s and 504s
tail -n 100 /var/log/apache2/error.log # Apache
journalctl -u php8.3-fpm --since "10 min ago" # PHP-FPM, dead processes
tail -n 100 storage/logs/laravel.log # the application, for 500s
df -h && free -m # full disk, exhausted memory
The order matters: the web server log says which layer failed, the application log says why. Starting with the second when the failure is a 502 means hunting for an error in a file that was never executed.
What to check with your host before blaming your code
Three things, and they take two minutes:
- The host status page. Maintenance on a shared database produces 500s for everybody at once.
- The quotas. Number of processes, memory per process, simultaneous database connections: exceeding them produces exactly the same symptoms as a bug.
- A failed payment. A service suspended for non-payment often answers with a 503, and the original notice went to spam three weeks ago.
Above all, remember that nobody will warn you spontaneously: a green status page while your site returns 500s is a perfectly normal situation from the host's point of view, since their machine is answering.
What to tell the client meanwhile
This is the paragraph nobody writes and everybody looks for. Two lines are enough, and they mention no code at all:
The site has been showing an error since 2:20pm. We have identified where it comes from and we are working on it. I will update you at 3pm.
Do not say "502 error", nobody knows what that is and it sounds like recitation. Do not promise a recovery time while the cause is unknown. And say something before you are asked: a client who discovers the outage themselves remembers the incident, a client who was told remembers the response.
The three diagnostic mistakes that cost the most time
Restarting before reading. A restart usually wipes the trace of what broke: the dead process comes back, the log starts again, and the failure returns two hours later with you no wiser. Read first, restart second, in that order, however strong the temptation.
Believing the code names the culprit. It names the layer that reported the problem, not the one that caused it. A 502 returned by Nginx is almost always a PHP problem, and an application 500 is sometimes a full disk, which is a system problem.
Treating an isolated incident as a trend. A single 502 at three in the morning, during a log rotation, needs no action. Three 502s in the same day do. The difference is only visible if something keeps the history, which is what monitoring genuinely adds over reading a log now and then.
What these codes do not tell you
They do not tell you whether the visitor saw the page. A user whose browser had it cached noticed nothing; another, arriving at the same moment from a search result, got the error full screen. They also do not tell you how many people are affected: an error hitting one specific route, an order form for instance, can produce a laughable number of 500s and cost a great deal.
What the three have in common
In all three cases the machine is up. Something answered. That already rules out DNS, the network and the host, and that is exactly what makes the code worth reading before anything else.
If nothing answers at all, you are looking at a different problem, and the first fifteen minutes are spent elsewhere.
Two neighbours deserve separating, because they are often filed with this family. A 404 is not a failure: it is the correct answer to a request for a page that does not exist, and it is triaged by other rules. A certificate warning is not an error code at all: the server answers perfectly, the browser refuses to display, and that failure leaves no trace in your logs.
The question nobody asks
Whichever code you got, the useful question comes afterwards: how long was it returned before you knew? A 500 that lasts four minutes is a non-event. The same 500 discovered the next morning by a customer is a different story, and the difference has nothing to do with the code.
It is also the only part that can be quantified: what an hour of downtime really costs depends far less on the nature of the failure than on how long it stayed on screen.
Frequently asked questions
Which is the most serious?
None of them is more serious than the others, they point to different layers. A 500 is your application, a 502 is the link between two servers, a 503 is a capacity or maintenance issue. What decides the severity is how long it lasts and how many visitors hit it.
Why do I sometimes see a 502 and sometimes a 504?
Both come from the machine in front, a proxy or load balancer. A 502 means the server behind it answered something unusable; a 504 means it did not answer in time. The first suggests a crash, the second a slowdown.
Does Google penalise a site that returns a 500?
Not as a punishment. But a crawler that keeps finding errors slows down its visits and can eventually drop the pages it cannot read. A short outage is harmless; one that lasts several days is not.
Never lose a backlink again
Add your sites and links, and let Expansel watch them for you.
Start free