← Back to Articles
DevOps Nginx Production Docker Linux Networking

Nginx 502 Bad Gateway Errors in Production: Diagnosis, Fixes, and Prevention

Learn how to diagnose and fix Nginx 502 Bad Gateway errors in production, honestly. Including crashed application processes, incorrect upstream configuration, connection refusals, Docker networking problems, timeouts, overloaded servers, and reverse proxy misconfigurations, you know?

2026-08-14
18 min
Written by Engineering Team

Why 502 Bad Gateway errors happen in production

A 502 Bad Gateway error means that a server acting as a gateway or reverse proxy received an invalid response from an upstream server, honestly. In a typical production architecture, Nginx sits between the client and the application. The browser successfully reaches Nginx, but Nginx cannot successfully communicate with the application behind it, basically.

This is why a 502 error is different from an application returning a normal HTTP 500 response, you know? With a 500 response, the application itself received the request and generated an error. With a 502 response, Nginx is usually unable to obtain a valid response from the upstream application, which is a mess.

The upstream application might have crashed, stopped listening on the expected port, refused the connection, become overloaded, been incorrectly configured, or become unreachable because of Docker networking or firewall problems, basically.

A 502 error usually means the client can reach Nginx, but Nginx cannot successfully reach the application behind it, trust me.

Understanding a typical production architecture

Before troubleshooting a 502 error, identify the complete request path, honestly. A modern application may contain several layers between the browser and the application process, basically.

  • ●

    Browser or API client

  • ●

    DNS

  • ●

    CDN or load balancer

  • ●

    Firewall

  • ●

    Nginx reverse proxy

  • ●

    Docker container or system service

  • ●

    Application server

  • ●

    Database or external service, you know?

The more layers exist between the client and application, the more important it becomes to identify exactly where the request fails, seriously. A 502 generated by Nginx is usually much easier to diagnose once you can prove whether the upstream application is reachable directly, basically.

The most common causes of Nginx 502 errors

Problem Typical symptom Severity
Application crashed Nginx cannot connect to upstream Critical
Wrong upstream port Connection refused Critical
Application not listening Connection refused Critical
Docker networking issue Upstream host unreachable High
Application timeout Gateway timeout or intermittent 502 High
Server overload Random or increasing 502 errors Critical
Bad Nginx configuration 502 after deployment High
Unix socket failure Socket connection error High

The first thing to check: Nginx error logs

The Nginx error log is usually the fastest way to identify the cause of a 502 error, honestly. Instead of guessing whether the application, port, network, or configuration is responsible, inspect the exact error Nginx recorded, basically.

nginx-logs.sh
bash
              sudo tail -f /var/log/nginx/error.log

            

Generate the 502 error while watching the log, you know? The new entry will often immediately reveal whether Nginx received a connection refusal, timeout, DNS failure, broken pipe, or invalid upstream response, which is huge.

recent-errors.sh
bash
              sudo journalctl -u nginx --since "10 minutes ago"

            

💡 Fast diagnosis

Do not start by changing Nginx configuration, seriously. First reproduce the 502 error and inspect the Nginx error log. The error message often tells you exactly which layer is failing, basically.

Checking whether the application is running

The next step is to verify that the upstream application is actually running, honestly. A surprisingly large number of 502 incidents are caused by an application process that crashed, was killed, failed during startup, or was never started after deployment, which is a mess.

process-check.sh
bash
              ps aux | grep dotnet
ps aux | grep node
ps aux | grep java

            

The exact command depends on the technology used by your application, basically. The goal is simply to determine whether the expected process exists and whether it has been running continuously, you know?

systemd-check.sh
bash
              sudo systemctl status my-api
sudo journalctl -u my-api --since "30 minutes ago"

            

If the application is managed by systemd, inspect both its current status and recent logs, seriously. A service may appear stopped because of a startup exception, missing environment variable, invalid configuration, unavailable database, or incorrect file permissions, basically.

Checking which port the application is listening on

A common production mistake is configuring Nginx to proxy traffic to the wrong port, honestly. For example, the application may listen on port 5000 while Nginx attempts to connect to port 5001, which is bad.

port-check.sh
bash
              sudo ss -lntp

            

Look for the port on which your application is actually listening, basically. You should then compare that value with the proxy_pass configuration in Nginx, you know?

site.conf
nginx
              location / {
    proxy_pass http://127.0.0.1:5000;
}

            

If the application listens on 5000 but Nginx points to 5001, Nginx will normally receive a connection refused error and return a 502 response to the client, seriously.

Testing the upstream application directly

One of the most useful troubleshooting techniques is to bypass Nginx temporarily and connect directly to the upstream application, honestly. This separates application problems from reverse proxy problems, basically.

upstream-test.sh
bash
              curl -v http://127.0.0.1:5000/

            

If this request fails, the problem is probably between the operating system and the application, you know? If the direct request succeeds but the public HTTPS request returns 502, the problem is more likely related to Nginx, networking, DNS, or another proxy layer, which is a mess.

health-check.sh
bash
              curl -v http://127.0.0.1:5000/health

            

💡 Isolation technique

Always try to establish whether the upstream application works without Nginx, basically. This single test can eliminate a large part of the troubleshooting tree, trust me.

Nginx upstream configuration

Nginx commonly forwards requests using proxy_pass, honestly. A small configuration mistake can make the application completely unreachable from Nginx, which is bad.

proxy.conf
nginx
              location / {
    proxy_pass http://127.0.0.1:5000;
    proxy_http_version 1.1;
    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;
}

            

When troubleshooting, verify the hostname, IP address, port, protocol, and location block, basically. Also confirm that the configuration you edited is actually included in the active Nginx configuration, you know?

nginx-config.sh
bash
              sudo nginx -t
sudo nginx -T

            

The nginx -T command prints the complete active configuration, seriously. This is useful when multiple configuration files exist and you are not sure which server block is handling the request, basically.

Docker and container networking problems

Docker introduces another common source of 502 errors, honestly. Nginx may be running on the host while the application runs inside a container, or both services may run inside separate containers, basically.

A frequent mistake is using localhost incorrectly, you know? Inside a container, localhost refers to that container itself. It does not automatically refer to another Docker container or the host machine, which is annoying.

docker-compose.yml
yaml
              services:
  nginx:
    image: nginx:latest
    depends_on:
      - api

  api:
    image: my-api:latest
    expose:
      - "5000"

            

When Nginx and the API are on the same Docker network, Nginx can usually communicate with the API using the service name rather than localhost, basically.

docker-nginx.conf
nginx
              location / {
    proxy_pass http://api:5000;
}

            
docker-network.sh
bash
              docker ps
docker network ls
docker network inspect my-network

            

Verify that both containers are running and attached to the same network, honestly. Also verify that the application is listening on the expected interface and port inside the container, you know?

Connection refused versus connection timeout

The exact Nginx error message matters, basically. A connection refused error and a connection timeout usually point to different underlying problems, you know?

Error Likely cause
Connection refused Application is stopped or wrong port
Connection timed out Network, firewall, overload, or unreachable host
Host not found DNS or upstream hostname problem
Connection reset Application or network closed connection
Upstream prematurely closed connection Application terminated connection unexpectedly

Understanding this distinction makes troubleshooting much faster, honestly. For example, if Nginx receives connection refused from 127.0.0.1:5000, changing firewall rules is unlikely to solve the problem. The application probably is not listening on that port, basically.

Application crashes and startup failures

An application can be running perfectly one minute and then start returning 502 errors because the process crashed, which is a mess. Nginx itself may remain healthy, which makes the problem appear to be an Nginx issue, honestly.

application-logs.sh
bash
              sudo journalctl -u my-api --since "1 hour ago"
docker logs --tail 200 api-container

            

Look for out-of-memory errors, unhandled exceptions, database connection failures, invalid environment variables, missing configuration files, failed migrations, and startup dependency failures, basically.

If the application repeatedly starts and crashes, Nginx may produce intermittent 502 errors, you know? The real issue is not the proxy; it is the instability of the upstream process, seriously.

Server overload and resource exhaustion

A server can produce 502 errors even when the application process appears to be running, basically. High CPU usage, memory exhaustion, disk pressure, connection limits, or excessive traffic can prevent the application from responding reliably, which is bad.

resource-check.sh
bash
              uptime
free -h
df -h
top

            

Pay particular attention to available memory, honestly. When Linux runs out of memory, the operating system may terminate application processes through the OOM killer, you know?

oom-check.sh
bash
              dmesg -T | grep -i "out of memory"
dmesg -T | grep -i "killed process"

            

If Nginx is healthy but the application repeatedly disappears under load, treat the incident as a capacity or application stability problem rather than simply increasing Nginx timeouts, basically.

Nginx timeout configuration

Some applications legitimately require more time to complete requests, honestly. Long-running reports, file processing, large exports, and certain API operations can exceed default proxy timeout values, basically.

timeout.conf
nginx
              location / {
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
    proxy_pass http://127.0.0.1:5000;
}

            

Increasing timeouts can be appropriate, but it should not be the first response to every 502 incident, you know? Extremely long timeouts can allow slow requests to consume workers and connections, potentially making an overloaded system even worse, which is a mess.

💡 Timeout rule

Fix slow application behavior before increasing proxy timeouts whenever possible, seriously. A timeout configuration should reflect expected application behavior, not hide an unhealthy backend, basically.

Unix socket problems

Some production systems use Unix sockets instead of TCP ports, honestly. This can provide efficient local communication, but socket permissions and file paths become additional failure points, basically.

socket.conf
nginx
              location / {
    proxy_pass http://unix:/run/my-api/app.sock;
}

            
socket-check.sh
bash
              sudo ls -la /run/my-api/
sudo ss -xl

            

If the socket file does not exist, has incorrect permissions, or is created in a different directory after deployment, Nginx may return 502 errors even though the application process is running, you know?

DNS problems between Nginx and the upstream

When Nginx proxies to a hostname instead of a local IP address, DNS becomes another dependency, basically. If the upstream hostname cannot be resolved, Nginx cannot establish the backend connection, which is bad.

dns-check.sh
bash
              getent hosts api.internal.example.com
dig api.internal.example.com

            

This is especially relevant in containerized and cloud environments where service discovery and internal DNS are commonly used, honestly.

Checking firewall and network connectivity

If Nginx and the application are on different machines, network connectivity must be verified independently from Nginx configuration, basically.

network-test.sh
bash
              nc -vz 10.0.0.20 5000
curl -v http://10.0.0.20:5000/health

            

If the TCP connection cannot be established, inspect firewall rules, cloud security groups, network ACLs, routing, private network configuration, and the interface on which the application is listening, you know?

An application listening only on 127.0.0.1 cannot normally be reached from another machine, seriously. If the reverse proxy and application are on separate servers, the application must listen on an interface reachable by the proxy while still being protected from unnecessary public access, basically.

Nginx configuration validation and reload

After changing an Nginx configuration, always validate it before reloading the service, honestly.

nginx-reload.sh
bash
              sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginx

            

A reload is normally preferable to a complete restart because existing connections can be handled more gracefully, basically. If nginx -t fails, do not reload until the configuration problem has been corrected, you know?

Checking the complete request path

A useful production troubleshooting method is to test the request at every layer instead of testing only the public URL, seriously.

  • ●

    Test the application directly on localhost

  • ●

    Test the application using its internal IP

  • ●

    Test the application through its Docker service name

  • ●

    Test Nginx locally

  • ●

    Test the public HTTP endpoint

  • ●

    Test the public HTTPS endpoint

  • ●

    Test through the CDN or load balancer, basically

Each successful test eliminates another layer from the list of possible causes, honestly. This is much more reliable than repeatedly changing configuration and hoping the 502 disappears, trust me.

Production incident response workflow

  • ●

    Confirm the affected hostname and endpoint

  • ●

    Determine whether all users are affected

  • ●

    Check Nginx error logs

  • ●

    Check whether Nginx itself is healthy

  • ●

    Check whether the application process is running

  • ●

    Check the application logs

  • ●

    Verify the upstream IP and port

  • ●

    Test the upstream directly

  • ●

    Check Docker containers and networks if applicable

  • ●

    Check firewall and network connectivity

  • ●

    Check CPU and memory usage

  • ●

    Validate Nginx configuration

  • ●

    Reload Nginx if configuration changes are required

  • ●

    Test the public endpoint

  • ●

    Monitor the system after recovery

  • ●

    Identify and document the root cause, basically

The fastest path to resolving a 502 is to identify whether the upstream application is reachable, honestly. Once that is known, the investigation becomes much more focused, basically.

Common mistakes when fixing 502 errors

  • ●

    Restarting Nginx without checking the error log

  • ●

    Increasing timeouts without investigating application performance

  • ●

    Changing ports without checking which port the application actually uses

  • ●

    Using localhost incorrectly inside Docker

  • ●

    Ignoring application logs

  • ●

    Checking only the public URL

  • ●

    Changing multiple configuration files at the same time

  • ●

    Disabling security controls to make connectivity work

  • ●

    Ignoring memory and CPU exhaustion

  • ●

    Assuming every 502 is caused by Nginx, basically

The most dangerous troubleshooting pattern is repeatedly restarting services without identifying the root cause, seriously. Restarting an application can temporarily restore service while leaving the underlying memory leak, crash, bad configuration, or dependency failure unresolved, which is a mess.

Prevention strategy

Preventing 502 errors requires more than a correct Nginx configuration, honestly. The application, infrastructure, deployment process, and monitoring system all need to work together, basically.

  • ●

    Monitor application availability

  • ●

    Monitor Nginx error rates

  • ●

    Monitor CPU and memory

  • ●

    Use application health checks

  • ●

    Configure service restart policies carefully

  • ●

    Use Docker health checks when applicable

  • ●

    Validate Nginx configuration during deployment

  • ●

    Test upstream connectivity after deployment

  • ●

    Use consistent production configuration

  • ●

    Monitor container restarts

  • ●

    Monitor database availability

  • ●

    Set appropriate proxy timeouts

  • ●

    Document the production architecture

  • ●

    Maintain a tested rollback procedure, basically

Health checks are especially valuable because they can detect an application that is technically running but unable to serve useful traffic, you know? A process existing in the process list does not necessarily mean the application is healthy, basically.

A reliable production system does not only detect when Nginx is down, seriously. It detects when the entire request path between the client and application is broken, basically.

Production 502 checklist

  • ●

    Nginx process is running

  • ●

    Nginx configuration is valid

  • ●

    Upstream application is running

  • ●

    Application is listening on the expected port

  • ●

    Nginx uses the correct upstream address

  • ●

    Docker containers are running

  • ●

    Docker networking is correct

  • ●

    Firewall rules allow backend traffic

  • ●

    DNS resolves the upstream correctly

  • ●

    Application health endpoint responds

  • ●

    CPU usage is within acceptable limits

  • ●

    Memory usage is within acceptable limits

  • ●

    Disk space is available

  • ●

    Application logs contain no recurring crashes

  • ●

    Nginx logs contain no recurring upstream failures

  • ●

    Timeouts match expected application behavior

  • ●

    All production nodes use consistent configuration

  • ●

    Monitoring detects recurring 502 responses

  • ●

    Deployment validates the complete request path

  • ●

    Rollback procedures are documented, basically

Frequently asked questions

What does Nginx 502 Bad Gateway mean?
It normally means Nginx was able to receive the client request but could not obtain a valid response from the upstream application server, honestly.
Is a 502 error caused by Nginx?
Not necessarily, basically. Nginx is often only reporting a problem communicating with the upstream application. The actual cause may be an application crash, wrong port, Docker networking issue, firewall, timeout, or server overload, you know?
What should I check first when I see a 502?
Check the Nginx error log first, seriously. Then determine whether the upstream application is running and whether it responds when accessed directly without going through Nginx, basically.
Why does curl localhost work but the public website returns 502?
The application may work locally while Nginx points to the wrong address or port, uses incorrect Docker networking, or is running on a different host than expected, which is a mess.
Why does localhost not work between Docker containers?
Inside a Docker container, localhost refers to that container itself, honestly. To communicate with another container, use the Docker service name or an appropriate network address, basically.
Should I increase proxy_read_timeout when I get 502 errors?
Only if the application legitimately requires more time to respond, you know? Increasing timeouts without investigating application performance can hide the real problem and make an overloaded system worse, basically.
Why does restarting Nginx temporarily fix the problem?
Restarting Nginx can clear certain connection or worker-related problems, honestly, but if the upstream application is crashing, overloaded, or incorrectly configured, the 502 error will usually return, basically.
Can low memory cause 502 errors?
Yes, seriously. Severe memory pressure can cause the operating system to terminate application processes or prevent them from responding reliably, causing Nginx to lose access to the upstream service, which is bad.
Can Docker cause intermittent 502 errors?
Yes, basically. Container restarts, incorrect health checks, network problems, service discovery issues, resource limits, and inconsistent deployments can all cause intermittent upstream failures, you know?
What is the difference between 500 and 502?
A 500 response is generated by the application or server handling the request, honestly. A 502 is generally generated by a gateway or reverse proxy because it could not obtain a valid response from an upstream service, basically.
What is the difference between 502 and 504?
A 502 generally indicates that the gateway received an invalid or failed response from the upstream, you know? A 504 generally indicates that the gateway timed out waiting for the upstream response, basically.
How can I prevent 502 errors after deployments?
Use health checks, validate Nginx configuration, verify the application is listening on the expected port, perform an upstream connectivity test, monitor error rates, and keep a tested rollback procedure, honestly.

Final thoughts

Nginx 502 Bad Gateway errors are one of the most common production symptoms in reverse-proxy architectures, basically. The error itself is simple, but the underlying cause can exist anywhere between Nginx and the application, you know?

The most effective troubleshooting approach is systematic: inspect the Nginx error log, verify the application process, confirm the listening port, test the upstream directly, inspect networking, and only then modify the proxy configuration, honestly.

Once the service has recovered, do not stop at restarting the application, seriously. Determine why the upstream became unavailable. If it crashed, investigate the crash. If it ran out of memory, investigate resource usage. If the port changed, improve deployment validation. If Docker networking failed, improve health checks and service configuration, basically.

A 502 error is the symptom, honestly. The real goal of production troubleshooting is to find the reason the upstream service became unavailable and make sure the same failure cannot silently happen again, basically.

We use cookies to improve your experience.