502 Bad Gateway Error: Complete Troubleshooting Guide for Web Servers and Load Balancers
Fix 502 bad gateway errors on nginx, Apache, AWS ALB, and Cloudflare. Step-by-step debugging with log analysis and proven solutions.
- Upstream server failures (PHP-FPM crashes, database timeouts) cause 80% of 502 errors
- Proxy configuration issues including timeout settings and connection limits are common culprits
- Network connectivity problems between proxy and backend servers trigger gateway errors
- Check upstream server status first, then examine proxy logs, finally verify network connectivity
- Most 502 errors resolve by restarting upstream services or adjusting timeout configurations
| Method | When to Use | Time | Risk |
|---|---|---|---|
| Restart upstream services | Service crashes or memory issues | 1-2 minutes | Low |
| Increase timeout values | Slow backend responses | 5 minutes | Low |
| Fix proxy configuration | Misconfigured upstream blocks | 10-15 minutes | Medium |
| Scale backend resources | High traffic overload | 15-30 minutes | Medium |
| Network troubleshooting | Connection refused errors | 30+ minutes | High |
Understanding the 502 Bad Gateway Error
A 502 Bad Gateway error occurs when a proxy server (nginx, Apache, load balancer) receives an invalid or no response from an upstream server. Unlike 503 Service Unavailable errors that indicate temporary overload, 502 errors specifically point to communication failures between proxy and backend services.
The error manifests differently across platforms:
- nginx: "502 Bad Gateway" with "upstream prematurely closed connection" in logs
- Apache: "502 Proxy Error" with "Error reading from remote server"
- AWS ALB: "502 Bad Gateway" with target health check failures
- Cloudflare: "Bad gateway" with "Error 502" and ray ID for tracking
Common Root Causes
Upstream Service Failures (60% of cases)
- PHP-FPM process crashes or memory exhaustion
- Application server timeouts (Node.js, Python, Ruby)
- Database connection pool exhaustion
- Out of memory conditions killing backend processes
Proxy Configuration Issues (25% of cases)
- Incorrect upstream server addresses or ports
- Timeout values too low for slow backend responses
- Connection limits exceeded
- SSL/TLS handshake failures between proxy and backend
Network Connectivity Problems (15% of cases)
- Firewall blocking connections between proxy and backend
- DNS resolution failures for upstream hostnames
- Network partitions or routing issues
- Port binding conflicts
Step 1: Quick Diagnostic Commands
Start with these immediate checks to identify the failure point:
# Check if upstream services are running
sudo systemctl status nginx
sudo systemctl status php8.1-fpm
sudo systemctl status mysql
# Verify network connectivity to backend
telnet backend-server 8080
nc -zv backend-server 3306
# Check recent error logs
sudo tail -f /var/log/nginx/error.log
sudo journalctl -u php8.1-fpm -f
Step 2: nginx 502 Bad Gateway Troubleshooting
Identify the Upstream Issue
Examine nginx error logs for specific error patterns:
# Look for upstream connection errors
sudo grep "upstream" /var/log/nginx/error.log | tail -20
# Common error patterns:
# "connect() failed (111: Connection refused)"
# "upstream prematurely closed connection"
# "upstream timed out (110: Connection timed out)"
Fix PHP-FPM Related 502 Errors
Most nginx 502 errors stem from PHP-FPM issues:
# Check PHP-FPM status and restart if needed
sudo systemctl status php8.1-fpm
sudo systemctl restart php8.1-fpm
# Monitor PHP-FPM processes
sudo tail -f /var/log/php8.1-fpm.log
# Check PHP-FPM pool configuration
sudo nano /etc/php/8.1/fpm/pool.d/www.conf
Key PHP-FPM settings to verify:
; Increase max children if getting connection refused
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
; Increase memory limit if processes are being killed
memory_limit = 256M
Adjust nginx Timeout Settings
Increase timeout values for slow backends:
# In /etc/nginx/sites-available/your-site
server {
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_read_timeout 300;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
}
# For reverse proxy setups
location / {
proxy_pass http://backend;
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
}
Step 3: Apache 502 Proxy Error Resolution
ProxyPass Configuration Issues
# Check current proxy configuration
sudo apache2ctl -S
# Common fix for ProxyPass timeout issues
<VirtualHost *:80>
ProxyPass /app/ http://backend:8080/
ProxyPassReverse /app/ http://backend:8080/
# Increase timeout values
ProxyTimeout 300
# Connection pool settings
ProxySet connectiontimeout=30
ProxySet retry=300
</VirtualHost>
Enable and Check Apache Proxy Modules
# Enable required proxy modules
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo systemctl restart apache2
# Check if modules are loaded
apache2ctl -M | grep proxy
Step 4: AWS Application Load Balancer 502 Errors
Target Health Check Failures
AWS ALB returns 502 when all targets are unhealthy:
# Check target group health
aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:region:account:targetgroup/name
# Common issues:
# - Security group blocking health check port
# - Health check path returning non-2xx status
# - Target instances stopped or terminated
Security Group Configuration
Ensure proper inbound rules:
{
"IpPermissions": [{
"IpProtocol": "tcp",
"FromPort": 80,
"ToPort": 80,
"UserIdGroupPairs": [{
"GroupId": "sg-alb-security-group-id"
}]
}]
}
Application Response Issues
Check if your application is properly handling requests:
# Test health check endpoint directly
curl -v http://instance-private-ip/health
# Check application logs for errors
sudo journalctl -u your-app-service -f
Step 5: Cloudflare 502 Bad Gateway
Origin Server Connectivity
# Verify origin server is accessible
curl -H "Host: yourdomain.com" http://origin-server-ip/
# Check if origin is returning valid responses
curl -I http://your-origin-server.com
SSL/TLS Issues
Cloudflare 502 often indicates SSL problems:
# Test SSL connection to origin
openssl s_client -connect origin-server:443 -servername yourdomain.com
# Common fixes:
# 1. Ensure SSL certificate is valid on origin
# 2. Set Cloudflare SSL mode to "Full" instead of "Full (strict)"
# 3. Check if origin supports SNI
Step 6: Database Connection Issues
Database connection problems frequently cause 502 errors:
# Check MySQL connection limits
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_connections';"
mysql -u root -p -e "SHOW STATUS LIKE 'Connections';"
# Monitor current connections
mysql -u root -p -e "SHOW PROCESSLIST;"
# Increase max_connections if needed
# Add to /etc/mysql/mysql.conf.d/mysqld.cnf:
# max_connections = 200
Connection Pool Configuration
For application servers, verify connection pool settings:
// Node.js example
const mysql = require('mysql');
const pool = mysql.createPool({
connectionLimit: 10,
host: 'localhost',
user: 'dbuser',
password: 'dbpass',
database: 'mydb',
acquireTimeout: 60000,
timeout: 60000
});
Step 7: Memory and Resource Issues
Check System Resources
# Monitor memory usage
free -h
top -o %MEM
# Check disk space
df -h
# Monitor I/O wait
iostat -x 1
# Check for OOM killer activity
sudo dmesg | grep -i "killed process"
sudo journalctl -k | grep -i "oom"
Increase Resource Limits
# Increase PHP memory limit
sudo nano /etc/php/8.1/fpm/php.ini
# memory_limit = 512M
# Increase nginx worker connections
sudo nano /etc/nginx/nginx.conf
# worker_connections 1024;
# Restart services
sudo systemctl restart php8.1-fpm nginx
Advanced Debugging Techniques
Network Packet Analysis
# Capture traffic between proxy and upstream
sudo tcpdump -i any -w 502-debug.pcap host backend-server and port 8080
# Analyze with wireshark or tcpdump
tcpdump -r 502-debug.pcap -A
Stress Testing
# Test with concurrent requests to identify breaking point
ab -n 1000 -c 50 http://your-site.com/
# Monitor during load test
watch -n 1 'ps aux | grep php-fpm | wc -l'
Prevention Strategies
Monitoring and Alerting
Set up monitoring for early detection:
# Create health check script
#!/bin/bash
response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/health)
if [ $response -ne 200 ]; then
echo "Health check failed with code: $response"
# Send alert
fi
Graceful Degradation
Implement circuit breakers and fallback mechanisms:
# nginx upstream with fallback
upstream backend {
server backend1:8080 max_fails=3 fail_timeout=30s;
server backend2:8080 max_fails=3 fail_timeout=30s;
server backup-server:8080 backup;
}
Capacity Planning
Regularly review and adjust resource allocation based on traffic patterns and growth projections.
Frequently Asked Questions
#!/bin/bash
# 502 Bad Gateway Diagnostic Script
# Run this script to quickly identify common 502 error causes
echo "=== 502 Bad Gateway Diagnostic ==="
echo
# Check web server status
echo "[1] Checking web server status..."
for service in nginx apache2 httpd; do
if systemctl is-active --quiet $service; then
echo "✓ $service is running"
WEB_SERVER=$service
break
fi
done
# Check upstream services
echo
echo "[2] Checking upstream services..."
for service in php8.1-fpm php8.0-fpm php7.4-fpm mysql mariadb postgresql; do
if systemctl is-active --quiet $service; then
echo "✓ $service is running"
elif systemctl list-unit-files | grep -q $service; then
echo "✗ $service is installed but not running"
echo " Try: sudo systemctl start $service"
fi
done
# Check recent error logs
echo
echo "[3] Recent error log entries..."
if [ "$WEB_SERVER" = "nginx" ]; then
echo "--- nginx errors ---"
sudo tail -n 5 /var/log/nginx/error.log 2>/dev/null | grep -E "(upstream|502|connect|timeout)"
fi
# Check resource usage
echo
echo "[4] Resource usage..."
echo "Memory: $(free -h | awk 'NR==2{printf "%.1f%% used\n", $3*100/$2}')"
echo "Disk: $(df -h / | awk 'NR==2{print $5 " used"}')"
echo "Load: $(uptime | awk -F'load average:' '{print $2}')"
# Check connectivity
echo
echo "[5] Testing connectivity..."
if command -v nc >/dev/null; then
if nc -z localhost 80; then
echo "✓ Port 80 is open"
else
echo "✗ Port 80 is not accessible"
fi
fi
# Quick fixes suggestion
echo
echo "[6] Quick fix commands:"
echo "sudo systemctl restart nginx php8.1-fpm"
echo "sudo tail -f /var/log/nginx/error.log"
echo "sudo systemctl status php8.1-fpm"
echo
echo "For detailed troubleshooting, check:"
echo "- /var/log/nginx/error.log"
echo "- /var/log/php*/fpm.log"
echo "- systemctl status [service-name]"Error Medic Editorial
Our DevOps engineering team has collectively resolved thousands of production incidents across web servers, cloud platforms, and distributed systems. We specialize in rapid diagnosis and systematic troubleshooting of HTTP errors, performance issues, and infrastructure failures.
Sources
- https://nginx.org/en/docs/http/ngx_http_upstream_module.html
- https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html
- https://support.cloudflare.com/hc/en-us/articles/115003011431-Troubleshooting-Cloudflare-5XX-errors
- https://httpd.apache.org/docs/2.4/mod/mod_proxy.html
- https://www.php.net/manual/en/install.fpm.configuration.php