Troubleshooting
App not answering on its port: fix health check fails
Seeing "didn't answer on port within 90 seconds"? Learn why the health check fails and how to listen on PORT and 0.0.0.0 in Express, Flask and FastAPI.
Updated 3 min read
Every release on DployHub is zero-downtime. We start the new version next to the old one and wait up to 90 seconds for it to answer HTTP on your health check path with any status below 500. Only then does traffic switch. If the new version never answers, the old one keeps running and the deploy is marked failed with the last 50 log lines. Here is how to read each failure message and fix it.
"Your app didn't answer on port P within 90 seconds"
The full message reads: "Your app didn't answer on port P within 90 seconds. Make sure it listens on 0.0.0.0 and uses the PORT environment variable (PORT=P), or change the port in the app settings." It has three usual causes:
- Your app listens on a hard-coded port that differs from the one in Settings.
- Your app binds to
localhostor127.0.0.1, so it is unreachable from outside the container. - Startup is slow (migrations, cache warm-up) and takes longer than 90 seconds.
We always set the PORT environment variable. Read it and bind to 0.0.0.0.
Express (Node.js)
const express = require('express');
const app = express();
app.get('/', (req, res) => res.send('ok'));
const port = process.env.PORT || 3000;
app.listen(port, '0.0.0.0', () => console.log('listening on ' + port));Flask (Python)
With auto-detection, Flask apps start with gunicorn app:app --bind 0.0.0.0:8000, which is already correct. If you run the file directly, bind explicitly:
import os
from flask import Flask
app = Flask(__name__)
@app.get("/")
def index():
return "ok"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8000)))FastAPI (Python)
The variable must be named app. A custom start command should pass both host and port:
uvicorn main:app --host 0.0.0.0 --port $PORTIf your app genuinely uses a different port, set "Port your app listens on" in Settings to match. See port and health checks.
"Your app kept answering with HTTP 5xx"
Symptom: "Your app kept answering with HTTP 5xx on /path for 90 seconds." Your app is running and reachable, but the health check path returns server errors. Typical causes are a missing environment variable (database URL, secret key), a database that is unreachable, or a health check path that requires login and crashes. For Django, a missing entry in ALLOWED_HOSTS is a classic cause.
- Check the last 50 log lines on the failed deploy for the stack trace.
- Confirm all required variables exist for this environment in the environment variables tab. Staging and live have separate sets.
- Point the health check path at a light route such as
/healththat returns 200 without touching the database. Redirects and 4xx statuses count as healthy.
"Your app stopped right after starting"
Symptom: "Your app stopped right after starting (exit code N)…". The process exited instead of serving. Exit code 1 usually means an uncaught error at startup, such as a missing module or bad config. Exit code 137 means it was killed for using more memory than you gave it; see app crashed: out of memory. Run the start command locally with the same environment variables to reproduce it.
Still failing?
Open the Logs tab for the environment to see runtime output, and compare it with the deploy log. If you cannot find the cause, raise a ticket and attach the deployment so we receive its status, error summary and recent log lines.
Frequently asked questions
Is my site down while the health check fails?
No. The previous version keeps serving until a new version passes the health check.
Why does it work on localhost but not on DployHub?
Locally, binding to localhost is fine. In a container the app must bind to 0.0.0.0 so traffic from outside the container can reach it.
Does a 404 on the health check path fail the deploy?
No. Any status below 500 counts as healthy. Only no answer at all or repeated 5xx responses fail it.
Related articles
- Port and health checks for zero-downtime deploysHow DployHub uses your port and health check path to release new versions with zero downtime, what the failure messages mean and how to fix them.
- Fix a failed build on DployHubYour deploy failed during the build? Learn what the common build errors on DployHub mean and how to fix detection, start command, clone and timeout issues.
- App crashed out of memory (exit code 137)Exit code 137 means your app ran out of memory. Learn how to confirm it in metrics, add more RAM, and tune Node.js heap size or gunicorn workers to fit.
- Set environment variables for staging and liveAdd API keys, database URLs and other settings as environment variables on DployHub, separately for staging and live, and apply them with a redeploy.
- View app logs, build logs and metricsRead runtime logs from staging or live, full build logs for every deploy, and CPU, memory and uptime charts for your app in the DployHub dashboard.