Website Not Loading: Server-Side Checklist

A systematic server-side checklist for diagnosing why a website is not loading, from DNS propagation to SSL errors and reverse proxy misconfigurations.

A Systematic Approach to Website Downtime

When a website is not loading, the failure can originate at any layer: DNS resolution, TCP connectivity, TLS negotiation, application server, database, or CDN. Jumping to conclusions wastes time. Instead, work through each layer from the outside in, ruling out causes as you go.

DNS Propagation Check

Before assuming a server problem, confirm that DNS is resolving correctly. DNS changes can take up to 48 hours to propagate globally, though most propagate within minutes with low TTLs.

# Query your authoritative nameserver directly (bypass caching)
dig yourdomain.com @ns1.yourdomain.com

# Compare with what resolvers see
dig yourdomain.com @8.8.8.8    # Google
dig yourdomain.com @1.1.1.1    # Cloudflare
dig yourdomain.com @9.9.9.9    # Quad9

# Check if the A record matches your expected IP
dig +short yourdomain.com

# Verify from multiple global locations
# Use https://dnschecker.org or https://whatsmydns.net

Common DNS problems:

Problem Symptom Fix
Missing A record NXDOMAIN Add A record in DNS panel
Wrong IP in A record Connection refused or wrong site Update A record
Stale cache Some locations see old IP Wait for TTL expiry, or lower TTL proactively
NS delegation broken SERVFAIL Check domain registrar's nameserver settings

HTTP Response Analysis

Once DNS resolves correctly, test the HTTP layer directly.

# Get full HTTP response including headers
curl -v https://yourdomain.com

# Follow redirects and show final response
curl -L -v https://yourdomain.com 2>&1 | head -50

# Check HTTP without TLS (to isolate TLS issues)
curl -v http://yourdomain.com

# Get just the status code
curl -o /dev/null -s -w "%{http_code}" https://yourdomain.com

# Include timing information
curl -w "\nDNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nTotal: %{time_total}s\n" \
     -o /dev/null -s https://yourdomain.com

Interpreting status codes:

Code Meaning Common Cause
200 OK (but page may error) Content issue
301/302 Redirect loop Check redirect chain with curl -L
400 Bad Request Malformed request or Host header issue
403 Forbidden Permissions, WAF block, or IP block
502 Bad Gateway Backend (Gunicorn/uWSGI) is down
503 Service Unavailable App crashed or overloaded
504 Gateway Timeout Backend too slow, not backend not running

SSL/TLS Handshake

SSL errors prevent the browser from loading the page at all. Use openssl s_client to diagnose.

# Full TLS handshake debug
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com

# Check certificate expiry
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null \
  | openssl x509 -noout -dates

# Test specific TLS version
openssl s_client -connect yourdomain.com:443 -tls1_2
openssl s_client -connect yourdomain.com:443 -tls1_3

# Check certificate chain completeness
openssl s_client -connect yourdomain.com:443 -showcerts 2>/dev/null \
  | grep -E "^(subject|issuer)"

Common TLS issues:

  • Certificate expired: Renew with Certbot (sudo certbot renew)
  • Incomplete chain: Server missing intermediate certificate
  • Wrong domain: Certificate issued for www but not apex domain (or vice versa)
  • Self-signed cert: Replace with a CA-signed certificate
  • SNI not configured: Nginx server_name directive missing

Server Resource Exhaustion

A site can become unreachable when the server runs out of CPU, memory, disk space, or file descriptors.

# Memory: look for OOM kills
sudo dmesg | grep -i "oom\|killed process" | tail -20
free -h

# CPU load
uptime
top -b -n 1 | head -20

# Disk space (full disk causes many silent failures)
df -h
du -sh /var/log/* | sort -rh | head -10

# Open file descriptors (approaching system limit = connection drops)
cat /proc/sys/fs/file-max
lsof | wc -l

# Check if the application process is running
systemctl status nginx
systemctl status gunicorn   # or your app server
ps aux | grep -E 'nginx|gunicorn|uwsgi|node'

If memory is exhausted, check for memory leaks in application workers or consider restarting the service as an immediate mitigation while investigating.

Reverse Proxy Misconfiguration

When Nginx or Apache sits in front of your application, misconfiguration is a common cause of 502/504 errors.

# Test Nginx configuration syntax
sudo nginx -t

# Check Nginx error log
sudo tail -50 /var/log/nginx/error.log

# Check if upstream (Gunicorn/uWSGI) is listening
ss -tlnp | grep :8000      # or whatever port your app uses
curl http://127.0.0.1:8000/ # test the backend directly

# Verify upstream block in nginx config
grep -r "upstream\|proxy_pass" /etc/nginx/sites-enabled/

Example correct Nginx proxy configuration:

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_connect_timeout 10s;
        proxy_read_timeout 60s;
    }
}

Common mistakes: missing proxy_set_header Host, wrong port in proxy_pass, socket file permission errors, or proxy_read_timeout too short for slow database queries.

CDN Cache Issues

If you use Cloudflare, Fastly, or another CDN, a cached error response can make a site appear down even after the origin is fixed.

# Check if you're hitting CDN or origin
curl -v https://yourdomain.com 2>&1 | grep -E "cf-ray|x-cache|age|server"

# Cloudflare cache status
# cf-cache-status: HIT (served from cache)
# cf-cache-status: MISS (fetched from origin)
# cf-cache-status: BYPASS (origin served directly)

# Check if origin is healthy (bypass CDN)
# Find origin IP from Cloudflare dashboard, then:
curl -H "Host: yourdomain.com" http://ORIGIN_IP/

# Purge Cloudflare cache via API
CF_ZONE_ID="your_zone_id"
CF_TOKEN="your_api_token"
curl -X POST "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/purge_cache" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{"purge_everything":true}'

Browser Developer Tools

When everything checks out server-side but the page still does not display correctly in a browser, use DevTools:

  1. Network tab: Shows all resource requests. Look for red rows (failed requests), timing waterfalls, and blocked requests.
  2. Console tab: JavaScript errors can prevent page rendering.
  3. Security tab (Chrome): Shows certificate details and mixed-content warnings.
  4. Hard refresh: Press Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac) to bypass browser cache.
# Simulate different clients with curl
# Mobile user agent
curl -A "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0)" https://yourdomain.com

# Check for mixed content (HTTP resources on HTTPS page)
# Use browser console or:
grep -r "http://" /var/www/yourdomain/templates/  # for static links

Always test from multiple networks and devices before concluding the issue is global — sometimes a problem is specific to one ISP, one country, or one browser version.