# 502 Bad Gateway After Deploying? 8 Causes and How to Fix Each

Build succeeded but the URL shows 502 Bad Gateway? The 8 real causes (wrong port, localhost binding, crashes, memory, env vars) and how to fix each one.

URL: https://blog.dockhosting.dev/fix-502-bad-gateway-after-deploy
Published: 2026-11-02 · Updated: 2026-11-02 · Author: Doughmi ILYAS

## Summary

- A 502 after a successful build almost always means the proxy can't reach your app: it isn't listening, or crashed.
- The two most common causes: not reading the PORT environment variable, and binding to 127.0.0.1 instead of 0.0.0.0.
- Run dock logs first: the crash message or the missing variable is usually in the last 20 lines.

ort const meta = {
  title: "502 Bad Gateway After Deploying? 8 Causes and How to Fix Each",
  seoTitle: "502 Bad Gateway After Deploy? 8 Causes and Fixes",
  description:
    "Build succeeded but the URL shows 502 Bad Gateway? The 8 real causes (wrong port, localhost binding, crashes, memory, env vars) and how to fix each one.",
  date: "2026-11-02",
  category: "Guides",
  tags: ["Troubleshooting", "502", "Deployment", "Node.js", "Python"],
  stack: ["nginx", "nodejs", "python"],
  tryLabel: "app",
  command: "dock logs",
  takeaways: [
    "A 502 after a successful build almost always means the proxy can't reach your app: it isn't listening, or crashed.",
    "The two most common causes: not reading the PORT environment variable, and binding to 127.0.0.1 instead of 0.0.0.0.",
    "Run dock logs first: the crash message or the missing variable is usually in the last 20 lines.",
  ],
  faq: [
    {
      q: "What does 502 Bad Gateway mean?",
      a: "The server in front of your app (a reverse proxy or load balancer) received your request but got no valid response from your app. Your app is down, crashed, still starting or listening on the wrong address or port.",
    },
    {
      q: "Why does my app work locally but return 502 in production?",
      a: "Locally you open the port you chose, on localhost. In production, the platform tells your app which port to use through the PORT environment variable and connects from outside the container, so the app must listen on process.env.PORT and on 0.0.0.0.",
    },
    {
      q: "How do I see why my app crashed?",
      a: "Run dock logs to tail build and application logs, or open the App output tab on the deploy in the dashboard, which shows what your app printed while starting.",
    },
  ],
};

The build is green and the deploy says live, but opening the URL gives you **502 Bad Gateway** (or it spins until it times out). This is the most common "it worked on my machine" moment in web hosting, and it nearly always comes down to one of eight causes.

## What a 502 actually means

Every hosting platform puts a **reverse proxy** in front of your app. It terminates HTTPS and forwards each request to your container. A 502 means the proxy forwarded the request and **got nothing usable back**. Your code may be fine: the proxy just can't reach it.

So start with one question: *is my process running and listening where the proxy expects it?*

```bash
dock logs   # build + application logs, live
```

## 1. Not listening on `PORT`

The platform assigns a port and passes it in the `PORT` environment variable. If you hard-code `3000` or `8000`, the proxy knocks on a door nobody answers.

```js
// Node.js
app.listen(process.env.PORT || 3000);
```

```python
# Python (FastAPI / Uvicorn)
uvicorn main:app --host 0.0.0.0 --port $PORT
```

## 2. Listening on localhost only

`127.0.0.1` (localhost) is only reachable from **inside** the container. The proxy connects from outside, so bind to `0.0.0.0`.

| Framework | Wrong | Right |
|---|---|---|
| Express / Fastify | `listen(port, "127.0.0.1")` | `listen(port, "0.0.0.0")` or omit the host |
| Flask dev server | `app.run()` | Run under Gunicorn: `gunicorn app:app` |
| Uvicorn | `--host 127.0.0.1` | `--host 0.0.0.0` |
| Next.js standalone | default host | `HOSTNAME=0.0.0.0` |

## 3. The app crashes on startup

The deploy succeeded, then the process exited. Look at the last lines of `dock logs` for an exception. The usual suspects:

- `Cannot find module` → a runtime dependency is in `devDependencies`, or `start` points to a file the build doesn't create.
- `ModuleNotFoundError` → the package is missing from `requirements.txt` / `pyproject.toml`.
- `KeyError: 'SECRET_KEY'` → see cause 4.

On DockHosting, the **App output** tab on a deploy shows what your app printed while starting, with the failing line.

## 4. A missing environment variable

Your `.env` file isn't deployed (and shouldn't be). Every variable your app reads at startup, such as API keys, `SECRET_KEY` or `NODE_ENV`, must be set in the project's environment variables. Then restart:

```bash
dock restart
```

> Fail fast with a clear message. A check like `if (!process.env.STRIPE_KEY) throw new Error("STRIPE_KEY is not set")` turns a mysterious 502 into a one-line log you can fix in seconds.

## 5. The database points at localhost

`postgres://localhost:5432/...` works on your laptop and nowhere else. Read the connection string from `DATABASE_URL`, which is injected when you attach a managed database. See [connecting to managed PostgreSQL](/connect-app-to-managed-postgresql).

## 6. Out of memory

If the process gets killed without an error, it probably ran out of memory. On the Free plan an app and its database share 512 MB. Common culprits are a large build step at runtime, an unbounded cache, or too many worker processes.

- Build at build time (`npm run build`), and only *start* at runtime.
- Lower worker counts (Gunicorn `--workers 2`).
- Paid plans give more room: 1 GB on Hobby, 3 GB on Pro and up to 4 GB per app on Team.

## 7. Slow startup

Apps that need a long time before they listen (for example JVM apps such as Spring Boot, or apps that run migrations first) can look dead while they start. DockHosting gives apps up to **5 minutes** to start listening before it marks a start as failed. If yours takes longer, move heavy work out of startup.

## 8. The app was asleep

On the Free plan, an app sleeps after 1 hour without visits. The first request wakes it, and DockHosting shows a **Waking up** page instead of an error while it starts. That's expected behavior, not a bug. Hobby and higher plans are always on.

## A 60-second checklist

1. `dock logs`: is there a stack trace?
2. Does the app read `PORT`?
3. Is it bound to `0.0.0.0`?
4. Are all environment variables set in the dashboard?
5. Does the database URL come from `DATABASE_URL`?
6. Is memory within the plan's limit?

Still stuck? Open a ticket from **Support** in the dashboard (a failed deploy has a button for it), or ask on [Discord](https://discord.gg/qvt2uNsZk3).

## FAQ

### What does 502 Bad Gateway mean?

The server in front of your app (a reverse proxy or load balancer) received your request but got no valid response from your app. Your app is down, crashed, still starting or listening on the wrong address or port.

### Why does my app work locally but return 502 in production?

Locally you open the port you chose, on localhost. In production, the platform tells your app which port to use through the PORT environment variable and connects from outside the container, so the app must listen on process.env.PORT and on 0.0.0.0.

### How do I see why my app crashed?

Run dock logs to tail build and application logs, or open the App output tab on the deploy in the dashboard, which shows what your app printed while starting.
