At 3:14 AM last November, my phone buzzed with an alert: "Client site is down." I was half asleep. I opened my laptop, checked the URL, and saw it: 502 Bad Gateway.

If you've run a website for any length of time, you know that feeling. The site is down, users are seeing an error, and you need to know what's wrong in the next 60 seconds.

The HTTP status code told me everything I needed to know. Here's the diagnosis I ran, and the fix.

What the 502 Meant

502 means the reverse proxy (Nginx in this case) received an invalid response from the upstream server (PHP-FPM). In plain English: PHP crashed.

Common causes:

  • PHP-FPM process hit a memory limit and was killed
  • The server was out of RAM and the OOM killer killed PHP
  • A recent code change broke PHP parsing

I SSH'd in and checked dmesg | tail. Sure enough: "Out of memory: Killed process (php-fpm)."

The server had 2 GB of RAM. MySQL was using 1.5 GB. PHP-FPM ran out.

How I Diagnose HTTP Errors Now

Before I open SSH, I check the HTTP status with our HTTP status checker. It takes 2 seconds and tells me which category of problem I'm dealing with.

Here's my mental map:

Status What It Means Where to Look
200FineProblem is elsewhere
301/302RedirectCheck destination
403Access deniedFirewall / permissions
404Page missingURL / routing
500Server errorPHP logs
502Proxy can't reach PHPPHP-FPM status
503Server overloadedResource usage
504Proxy timeoutBackend speed

The status code narrows it down from "everything is broken" to "one specific layer is broken." That's worth a lot at 3 AM.

The 500 Error Nightmare

500 is worse than 502, because "Internal Server Error" is vague. It could be:

  • A PHP syntax error
  • A database connection issue
  • A memory limit
  • A permissions problem
  • A bad .htaccess or Nginx config

When I see 500, I immediately open the error log:

tail -50 /var/log/nginx/error.log
tail -50 /var/log/php-fpm/error.log

The answer is almost always there. If it's not, I temporarily enable display_errors in PHP and refresh the page.

What I Learned from That Night

Three things:

  1. Set up monitoring. I now use UptimeRobot (free tier). It pings my sites every 5 minutes and texts me if anything is down. That night, I found out from a client, not from my monitor.
  2. Cap MySQL memory. The default MySQL config uses more memory than it needs. I now set innodb_buffer_pool_size = 128M on every small VPS I run.
  3. Learn the status codes. Not memorized — just know what category each one belongs to. That alone cuts diagnosis time in half.

The Free Tool I Use Weekly Now

Every Monday I run a quick check on my own sites using our HTTP status checker. It's 30 seconds of work and catches small issues before they become 3 AM emergencies.

If you run more than one site, use the bulk HTTP checker — it checks up to 50 URLs in one run.

That 30 seconds has saved me at least two late-night incidents since the 502 nightmare.

The Real Lesson

Most site outages aren't mysterious. The HTTP status code tells you which layer broke. From there, you just need to know where the logs are.

The status code doesn't fix anything. But it points you in the right direction — and at 3 AM, that's the difference between a 10-minute fix and a 3-hour one.

Do the Monday check. Set up the monitoring. Cap your MySQL memory. Future you will thank present you.