“The web server reported a bad gateway error.” usually means the server at the edge reached your application or upstream service, but the upstream returned an invalid response, timed out, crashed, or was unreachable. In plain English: the browser reached something, but that something could not get a clean answer from the app behind it.
A bad gateway is frustrating because it sits in the middle. The domain may be fine. TLS may be fine. The frontend may be fine. Then the request hits the proxy, load balancer, CDN, gateway, or platform router and falls into the gap between “I found your app” and “your app answered correctly.” That gap is where production debugging earns its coffee.
This guide takes the error apart from the outside in: what it means, how to isolate the failing layer, what to check in deploy logs, and how to keep the same 502 from coming back after the next release.
Table of contents
- What the error means
- Where a bad gateway error happens
- Start with the fastest checks
- Use logs to find the failing layer
- Common causes in deployed apps
- How to fix a 502 bad gateway error
- How to prevent the next one
- FAQ
What the error means
A bad gateway error is an HTTP 502 response. The gateway or proxy received an invalid response from an upstream server. That upstream might be your Node app, Python API, container, backend service, database-facing API, or another proxy in front of the app.
The important detail is this: a 502 is not usually a browser problem. Refreshing might work if the outage is brief, but the real cause normally lives in application startup, runtime crashes, networking, proxy configuration, upstream timeouts, or resource limits.
The MDN 502 Bad Gateway reference defines it as a server acting as a gateway or proxy receiving an invalid response from the upstream server. That definition is accurate, but it does not tell you which server is guilty. Your job is to narrow the chain.
Where a bad gateway error happens
A typical production request looks like this:
Browser → DNS → CDN / edge proxy → platform router → app process → dependencies
A bad gateway usually appears between the edge proxy and the app process, or between one internal service and another. The proxy expected an HTTP response and got one of these instead:
- no connection
- connection refused
- a process that crashed mid-request
- malformed HTTP response
- upstream timeout
- TLS handshake failure
- a response larger or slower than the gateway allows
That is why “the site is down” is too vague. A static page can load while the API returns 502. The homepage can work while /api/checkout fails. One region can be healthy while another has a broken deploy. The error is a symptom, not a location.
If your project combines static pages and backend services, keep those routes visible. RunxBuild lets teams ship static sites, APIs, databases, and Docker services from one deployment path, which makes it easier to ask the right question: did the static asset fail, or did the backend route fail?
Start with the fastest checks
Before rebuilding the world, do the cheap checks. They often catch the boring cause.
- Open the failing URL in a private window or with
curl. - Check whether every route fails or only one route.
- Confirm the latest deploy actually completed.
- Check the app logs around the first 502.
- Confirm the service is listening on the expected port.
- Confirm environment variables exist in the deployed runtime.
- Check whether the database or upstream dependency is reachable.
- Roll back if the failure started with the last release.
Use curl so you can see headers and status without browser noise:
curl -i https://example.com/api/health
If you have a health endpoint, test that too:
curl -i https://example.com/health
A healthy static page plus a failing health endpoint points toward the application runtime. A failing domain before any app logs appear may point toward DNS, proxy, TLS, or platform routing.
Use logs to find the failing layer
A 502 without logs is a locked room mystery with a URL. Logs tell you whether the request reached the app, whether the app crashed, or whether the gateway failed before your code ran.
Look for these patterns:
| Log pattern | Likely meaning |
|---|---|
| No app log for the request | request failed before reaching the app |
| app startup error | deploy built, but runtime never started |
EADDRINUSE or port mismatch | app listens on the wrong port or address |
| database connection timeout | app started but cannot reach required dependency |
| out-of-memory restart | app is crashing under load or startup work |
| upstream timeout | request takes longer than the gateway allows |
On RunxBuild, deploy logs and runtime logs are part of the debugging loop. Start with the relevant service docs for your stack, such as Node services, Python services, or Docker services, then compare the configured start command and port behavior against what the logs show.
If the error follows a release, do not debate it in Slack for twenty minutes. Compare the previous successful deploy with the failing one: runtime version, environment variables, build command, start command, migrations, and dependency changes.
Common causes in deployed apps
The app is not listening on the expected port
Many platforms inject a PORT environment variable. If your app ignores it and hardcodes 3000, the router may not be able to reach the process.
Use this pattern in Node:
const port = process.env.PORT || 3000;
app.listen(port, '0.0.0.0', () => {
console.log(`Server listening on ${port}`);
});
Binding to 127.0.0.1 can also cause trouble in containerized environments. Use 0.0.0.0 when the service needs to receive traffic from outside the container.
The start command is wrong
A build can pass while the runtime command fails. This happens when the project builds to dist/, but the start command still points to server.js, or when a TypeScript app forgets to compile before starting.
Good logs make this obvious. Bad logs make people try random npm scripts until something moves. Prefer explicit scripts:
{
"scripts": {
"build": "tsc",
"start": "node dist/server.js"
}
}
Required environment variables are missing
A missing DATABASE_URL, API key, session secret, or runtime flag can crash the app on startup. Worse, some apps start successfully and only crash when the first request touches the missing value.
Keep environment variables visible in your deployment configuration and fail fast on startup when required values are missing. RunxBuild’s docs on static builds and service configuration are useful reminders: local .env files do not magically appear in production.
The database is unreachable
The app may start, but every request that touches the database fails. That can produce 502 errors if the process crashes, times out, or returns malformed responses under connection pressure.
Check:
- database hostname and port
- credentials
- SSL mode
- private network rules
- max connections
- migration state
If database-backed routes are failing, review the RunxBuild managed database docs and database network security. A database URL is not just a string. It is a route, permission boundary, and resource limit all pretending to be one line of text.
The app times out
A gateway timeout and a bad gateway are different status codes, but slow upstreams often travel together. If the app takes too long to respond, the proxy may close the connection or return an error before the app finishes.
Common timeout causes include:
- slow database queries
- cold startup work inside request handlers
- external API calls without timeouts
- file uploads routed through the wrong service
- background jobs running inside web requests
Move long work out of the request path. If a task can run in the background, make it a worker or job instead of making users stare at a spinning tab.
The process is crashing under memory pressure
A service can look fine at startup and still fall over when traffic arrives. Watch for restarts, out-of-memory messages, and rising memory usage.
If the service needs more headroom, use the RunxBuild hosting calculator to estimate the cost before resizing by instinct. More memory can be the right fix, but it should follow evidence, not superstition.
How to fix a 502 bad gateway error
Use this order. It moves from fast evidence to deeper fixes.
1. Confirm the failing route
Check whether the error affects one route, one service, or the whole domain. If only API routes fail, your static host is probably not the issue. If everything fails before app logs appear, focus on routing, DNS, TLS, or service availability.
2. Read the latest deploy logs
Look for startup failures, missing modules, bad commands, migration failures, or port messages. The first error usually matters more than the last one. Later logs are often just the app falling down the stairs after the first push.
3. Check the runtime port and bind address
Make sure the app listens on process.env.PORT or the platform’s configured port. In containers, bind to 0.0.0.0, not just localhost.
4. Verify environment variables
Compare local development with production. If the app needs DATABASE_URL, SESSION_SECRET, or a framework-specific runtime flag, confirm it exists in the deployed service.
5. Test the health endpoint
A health endpoint should return a clear 200 when ready and a non-2xx status when not ready. If you do not have one, add it. A small health check response protocol turns vague downtime into a specific failure.
6. Check upstream dependencies
If the app starts but routes fail, test the database, cache, queue, or internal API from the runtime environment. Do not assume local connectivity means production connectivity.
7. Roll back when the release is clearly bad
If the last deploy introduced the 502 and the previous release was healthy, roll back first and investigate after users are back online. Debugging is easier when the production fire is not still spreading.
Cloudflare’s 502 and 504 troubleshooting guide is also useful when a CDN or edge layer is in the path, especially for distinguishing origin failures from edge-specific issues.
How to prevent the next one
The best 502 fix is the one you do before users see it.
Add a real health endpoint
Your app should expose a fast health endpoint that checks readiness without becoming a full diagnostic suite. It should catch obvious startup and dependency failures before traffic moves to a new instance.
Fail fast on missing configuration
If a required environment variable is missing, crash at startup with a clear message. Do not wait until the first user triggers the broken path.
Keep build and start commands explicit
A platform should not have to guess how your app starts. Put the commands in package.json, a Dockerfile, or deployment settings. Then keep them in sync with the framework output.
Separate web requests from background work
A request should not perform a slow report, model job, media conversion, or long external sync while the gateway waits. Use background workers, queues, or scheduled jobs for work that does not need to finish before the HTTP response.
Watch deploys, not just uptime
Many teams monitor uptime but ignore deploy health. The better signal is: did the new release start, become ready, receive traffic, and keep error rates stable? That is the difference between knowing a site exists and knowing a release worked.
The 502 page is not the villain. It is the messenger. The fix is a deployment path with visible logs, clear health checks, correct runtime configuration, and enough resource headroom for the app you are actually running.
FAQ
What does “the web server reported a bad gateway error” mean?
It means a gateway, proxy, CDN, or platform router could not get a valid response from an upstream server. The upstream might be your app process, an internal service, or another proxy. The problem is usually server-side, not a browser issue.
Is a 502 Bad Gateway error my fault?
If you are a visitor, usually no. If you own the site or app, the cause may be in your deployment, app runtime, upstream service, network path, or CDN configuration. Logs are the fastest way to tell which layer failed.
How do I fix a 502 Bad Gateway error on my website?
Start by checking deploy logs, runtime logs, service health, port configuration, and required environment variables. Then test dependencies such as the database or internal API. If the issue started with the last release, roll back while you investigate.
Can DNS cause a bad gateway error?
DNS problems usually cause lookup or connection errors, not classic 502 responses. However, incorrect DNS or proxy configuration can route traffic to the wrong origin, which may then return a gateway error. Check DNS when the request never reaches the expected service.
What is the difference between 502 and 504?
A 502 means the gateway received an invalid response from the upstream server. A 504 means the gateway timed out waiting for the upstream response. In practice, both point to the path between the proxy and the application.
Why does refreshing sometimes fix a 502?
Refreshing can work when the upstream failure is brief, such as a restarting process, a deploy rollout, or a temporary connection issue. If the error keeps returning, you need logs and health checks rather than more refreshes.