What a 500, 502, 503 or 504 Is Actually Telling You
A field guide to the status codes a monitor reports at 3am. What each one means, what usually causes it, and the timing patterns that tell you where to look first.
An alert says your site returned a 502. Or a 504, or a 403 that was a 200 yesterday. The
number is the first and often the only clue you get, and each one narrows the search in a
different direction.
This post goes through what each code is telling you, what tends to cause it, and what the timing adds on top.
How to read a status code
The first digit is the category. 2xx means it worked. 3xx means look somewhere else. 4xx
means the client did something the server rejects. 5xx means the server, or something in front of
it, failed.
That "something in front of it" matters more than anything else on this page. Almost every
production site has layers: a CDN or WAF, a load balancer, a reverse proxy like nginx, and behind
all of it the application. Any layer can generate a status code, and the code tells you which layer
gave up. A 502 is a proxy saying the app did not answer properly. A 500 is usually the app
itself saying it crashed. Learning which layer speaks which code is most of the skill.
Barkme counts only 2xx as up. Everything else opens an incident once it is confirmed, including
redirects, which surprises people until they read why.
The 5xx family
500 Internal Server Error
The application ran and threw an error it did not handle. An unhandled exception, a PHP fatal, a missing environment variable, a database it cannot connect to, a permissions problem on a file it needs to write.
When a monitor starts seeing 500 immediately after a deploy, the deploy is the cause until proven
otherwise. When it starts seeing 500 with no deploy, look at what changed underneath: a
dependency that auto-updated, a database that filled up, a certificate the app uses to talk to
something else, a third-party API that changed its response shape.
A 500 with nothing in the application log usually means the error happened before logging was
set up, in configuration loading or bootstrapping. Check the web server's error log.
502 Bad Gateway
A proxy tried to hand the request to the application and got back something it could not use. The overwhelmingly common cause is that the application process is dead or has stopped listening. PHP-FPM crashed, the Node process ran out of memory and was killed, a container restarted and has not come back, the socket path or port in the proxy config is wrong after a change.
Less common: the application responded, but with headers too large for the proxy's buffers, or the proxy and the upstream disagree about TLS.
A 502 at the same time every night is a backup or a cron job restarting the app. A 502 for
thirty seconds after every deploy is a deploy process that stops the old version before the new one
is ready to accept connections.
503 Service Unavailable
The server is up and deliberately refusing. Maintenance mode is the intended use, and Laravel's
php artisan down returns exactly this. Overload is the other common one: a queue that is full, a
worker pool with every process busy, an autoscaling group still scaling.
If your monitor sees 503 and you did not put the site into maintenance, something is saturated.
Response times in the checks leading up to it will usually show the climb.
504 Gateway Timeout
The proxy handed the request to the application and the application took too long to answer. The application is alive and busy.
The usual suspects are a database query that used to be fast and has stopped being fast now that
the table has grown, a lock that is being held, an external API call with no timeout of its own, or
a report that was never meant to be run from a web request. PHP's execution limit is often longer
than the proxy's timeout, so PHP is still happily working on the request after nginx has given up
and sent the visitor a 504.
A 504 that gets more frequent over weeks is data growth. A 504 that appears at 9am on Monday is
load. A 504 on one endpoint only is that endpoint.
The Cloudflare 52x codes
If Cloudflare sits in front of your site, it has its own codes for problems talking to your origin, and they are precise enough to memorise.
| Code | What happened | Where to look |
|---|---|---|
520 |
The origin sent a response Cloudflare could not make sense of | Origin crashed mid-response, or sent something malformed |
521 |
The origin refused the connection | Web server down, or a firewall blocking Cloudflare's IP ranges |
522 |
The connection to the origin timed out | Origin unreachable or overloaded at the network level |
523 |
Cloudflare could not route to the origin | DNS or routing for the origin address is broken |
524 |
Connected, but the origin never answered | Same as a 504: something slow, past Cloudflare's 100-second limit |
525 |
The TLS handshake with the origin failed | Origin's TLS configuration is broken |
526 |
The origin's certificate did not validate | Origin certificate expired or wrong, in Full (strict) mode |
A 52x from Cloudflare with a healthy origin usually means a firewall rule that blocks
Cloudflare's address ranges, often added by someone hardening the server without knowing what sat
in front of it.
The 4xx family
4xx codes blame the client, and when the client is your monitor, that deserves attention, because
a monitor sends the same request every time. Something changed on the server side.
401 and 403
401 means credentials are required and none were given. 403 means the server understood
exactly who was asking and said no.
When a page that used to return 200 starts returning one of these, the list of causes is short.
A web application firewall has decided your monitor looks like a bot. Someone turned on
Cloudflare's bot fight mode or a similar challenge, which answers with a 403 and a JavaScript
puzzle the monitor cannot solve. A geo-block was added and the monitor's location is in it. Basic
auth was enabled on staging and the monitor was not told. A token expired.
The tell is that visitors are fine and only the monitor is blocked. Allowlist the monitor's address, or point it at a route the firewall does not guard.
404 Not Found
The server is up and the path does not exist. For a monitored URL that used to work, a deploy removed or renamed the route, a CMS page was deleted, or, less obviously, DNS now points at a different server that has no idea what this hostname is and serves its default site.
That last one deserves a check when a 404 appears with no deploy. Look at what the response body
says. If it is somebody else's default page, the problem is in DNS, and
how DNS works will help.
429 Too Many Requests
Rate limited. If the only client hitting that limit is your monitor, the interval is too aggressive for the endpoint, or a rate limit was added without an exemption. If real users are hitting it, the limit is doing its job and the alert is telling you about load.
400, 405, 408, 410 and 451
400 is a malformed request, which from a monitor almost always means a proxy in between mangled
something. 405 means the method is wrong: a HEAD check against a route that only accepts
GET, or a route that moved to POST. 408 is the server timing out waiting for the client, rare
from a monitor. 410 is a deliberate "gone forever," which is a 404 with a note attached. 451
means the content is blocked for legal reasons in that region.
The 3xx family
Redirects are healthy responses. They are also a common way for a site to be broken while appearing
fine. A 301 to a parked domain, a redirect loop, an http to https redirect on a site whose
certificate has expired, all look like "the server answered" to a monitor that is too generous.
That is why Barkme counts them as down, and why the right fix is to monitor the URL at the end of the chain. A redirect that appears out of nowhere on a monitored URL deserves a look regardless, because injected redirects to spam pages are a standard symptom of a compromised site.
No status code at all
Some failures never produce a number, and they are often the worst.
Timeout. No response within the limit. Either the network path is broken or the server is so overloaded it cannot even start answering.
Connection refused. The machine was reached and nothing is listening on the port. The web server itself is down, or a firewall is bouncing the connection.
DNS failure. The name does not resolve. The domain expired, a nameserver change went wrong, or the domain is on a filtering list and the resolver refuses to answer.
TLS failure. The handshake failed. An expired or mismatched certificate, or a broken chain, explained here.
Barkme records each of these with its own reason so the alert says what it saw, and treats every one as down. A visitor does not care which layer failed. They typed the address and nothing came back.
Reading the pattern
The code narrows the search. The timing usually finishes it.
- Right after a deploy: the deploy.
- Same time every day: a scheduled job, a backup, a log rotation restarting something.
- Under load, recovers by itself: capacity. Look at the response times before the failure.
- Getting slowly worse over weeks: data growth. A query that no longer fits its index.
- One endpoint only: that endpoint's code or its dependencies.
- Only the monitor, visitors unaffected: a firewall, a bot filter, or a rate limit.
- Some visitors, and you cannot reproduce it: DNS, and probably a blacklist.
- Everything at once, at midnight: something expired.
The layer that reports the error is rarely the layer that caused it. A 502 from nginx is nginx
being honest about an application that is missing. Start one layer further back than the code
suggests.
Barkme watches your sites around the clock and barks the moment one goes down. Free plan, no card required.
Keep reading
More from the blog
Uptime Monitoring Tools in 2026: An Honest Comparison
Nine uptime monitoring services side by side, including ours. Who each one suits, where each one is weak, and the one check almost none of them run.
Fail2ban: A Practical Way to Quiet the Bots Hammering Your Server
Every server on the internet gets probed within minutes of going online. Fail2ban reads your logs and bans the addresses doing it. Installation, the SSH jail, a custom jail for .env scans, and how to avoid banning yourself or your own uptime monitor.
How Often Should You Check Your Website Is Up?
Checking every 30 seconds is not four times better than every two minutes. How check frequency actually maps to the downtime your customers notice, and how to pick an interval per site.