Website Down? The Exact Checklist to Diagnose and Fix It
Your website is down — or at least someone says it is. The next fifteen minutes go one of two ways: methodical layer-by-layer isolation that finds the fault fast, or panicked tab-switching, cache-clearing and server-rebooting that makes things worse. The difference is having a runbook before you need one. This is that runbook: confirm the outage is real, then walk the stack from DNS to TLS to server to application, with the actual commands at each step.
Step 0: Confirm it's actually down
"Down for me" and "down" are different incidents. Before touching anything:
- Check from outside your network. Your office DNS, VPN, or a poisoned local cache can make a healthy site look dead. Load it from your phone on mobile data, or run a check from an external vantage point — the free uptime test requests your URL from outside and shows the status code, response time and any error.
- Check the specific failing URL, not just the homepage. "The site is down" often means one route, one asset host, or one API endpoint.
- Ask what changed. A deploy, a DNS edit, a certificate renewal, an infrastructure migration in the last 24 hours is the prime suspect. Start there before starting from scratch.
If external checks pass and only you can't reach it, you have a local/network problem, not an outage. Otherwise, work down the stack.
Step 1: DNS — does the name resolve?
If DNS is broken, nothing after it matters.
dig +short example.com A
dig +short example.com AAAA
No answer, or the wrong IP? Compare what different resolvers say:
dig +short example.com @1.1.1.1
dig +short example.com @8.8.8.8
- Both return nothing: check your zone at the DNS provider — a deleted record, a broken zone edit, or (worst case) an expired domain. Also verify the delegation:
dig +short example.com NSshould list your actual nameservers. - Resolvers disagree: a recent DNS change is still cached; old records live until TTL expiry (we cover TTL strategy and change detection in DNS monitoring: what to actually watch).
- Wrong IP entirely: either a fat-fingered record or, if you didn't change anything, treat it as possible hijacking and check your registrar/DNS-provider account immediately.
DNS resolves correctly? Next layer.
Step 2: TLS — does the handshake succeed?
An expired or misconfigured certificate blocks every browser at the door while your server sits there perfectly healthy.
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -dates -subject -issuer
Check three things:
notAfterin the past → expired certificate. Renew and — critically — reload the web server, since a renewed cert on disk does nothing until nginx/Apache reloads it.- Subject/SAN doesn't cover the hostname → hostname mismatch (classic after adding a subdomain or moving behind a new load balancer).
- The handshake itself fails (connection refused/reset on 443) → the web server or load balancer isn't listening; that's a server-layer problem, keep going.
A quicker read on all of this: the free SSL checker reports expiry, chain and hostname match in one shot. And if this step is how you found out the cert expired, read our guide to SSL certificate monitoring after the incident — this failure mode is entirely preventable.
Step 3: Server — does anything answer?
Now talk to the server directly and read the response headers:
curl -sv -o /dev/null https://example.com
curl -I https://example.com
Interpret what you get:
- Connection timed out → the host is unreachable: crashed instance, firewall/security-group change, or a provider outage. Check your cloud console and the provider's status page.
- Connection refused → the machine is up but nothing listens on the port: web server crashed or was stopped. SSH in;
systemctl status nginx(or apache2/caddy) and restart if dead. - 502 Bad Gateway / 504 Gateway Timeout → the proxy is alive but the app behind it isn't answering: crashed app process, exhausted PHP-FPM/worker pool, or a hung upstream.
- 503 Service Unavailable → deliberate maintenance mode left on, or an overloaded backend shedding load.
- 500 Internal Server Error → the app is running and failing. That's the next layer.
Step 4: Application — it answers, but wrongly
The server responds; the application is the problem. On the box:
- Read the error log first, not the code.
tail -100your app and web-server error logs — the actual exception is almost always sitting right there. - Check disk space:
df -h. A full disk is a spectacular generator of weird, unrelated-looking failures (sessions, logs, database writes all failing at once). - Check the database: is the process up, are connections being refused, did it hit
max_connections? - Check the last deploy. If the timeline matches, roll back first and diagnose second. Reverting to known-good beats debugging under fire.
While you fix it: communicate
Silence during an outage costs more trust than the outage. If you have a status page, use it within the first few minutes: acknowledge ("We're investigating elevated errors"), update as you learn, and post when resolved. A short honest update beats a detailed one that arrives an hour late — and it deflects the support-ticket flood so you can actually work the problem.
Afterward: the 30-minute post-incident review
Same week, while memory is fresh, write down four things: what happened (timeline), how you found out (a monitor? a customer? — if it was a customer, that's finding #1), what fixed it, and what would have prevented or shortened it. Turn the last answer into tickets. One process fix per incident compounds fast.
Get paged before your customers notice
Every step above assumes you know the site is down. The teams that recover fastest are the ones alerted by a machine within a minute — with the failing layer already identified. CompleteStatus checks your site continuously, confirms failures with a second probe before alerting (no 3 AM false alarms), and monitors each layer of this runbook separately — DNS records, certificate expiry and validity, response codes, keywords and response times — plus status pages for the communication step, so the diagnosis above is largely done before you've opened a terminal.
Run the free uptime test to check any site right now, then set up monitoring free — 10 monitors on the free tier, commercial use allowed — so the next incident starts with an alert, not an angry email.