Express, Fastify, Hono, NestJS and plain Node apps all deploy the same way: we run your start script. The only requirements are the port and the bind address.
Last updated
These are the defaults. Override any of them in Settings → Build.
Listen on the port we give you, on all interfaces:
Express
const port = process.env.PORT || 3000; app.listen(port, '0.0.0.0');
Fastify
await fastify.listen({
port: Number(process.env.PORT) || 3000,
host: '0.0.0.0',
});Hono
serve({
fetch: app.fetch,
port: Number(process.env.PORT) || 3000,
hostname: '0.0.0.0',
});NestJS
await app.listen(process.env.PORT ?? 3000, '0.0.0.0');
Then make sure package.json has a start script. For TypeScript, compile in build and run the output:
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}For NestJS use "build": "nest build" and "start": "node dist/main". We build on Node 22 by default, and engines.node in package.json overrides it. Dev dependencies are installed during the build, so build tools like tsc or the Nest CLI can live there.
Add variables in the project's settings. They're available both while the app builds and while it runs, so build-time values (like framework-public keys) work without extra setup. See Environment variables. Read them with process.env.NAME. Never commit a .env file.
Add a Postgres addon (or Redis) and DATABASE_URL (or REDIS_URL) is injected automatically. Read it with process.env.DATABASE_URL.
There's no separate pre-deploy step yet, so run migrations from the Build command in Settings → Build (for example npm run build && npx prisma migrate deploy) or before the server starts. Make migrations safe to run more than once.
<project-slug>.ethiodeploy.com. Every push to the default branch redeploys, and the old version keeps serving until the new one is healthy.Health check times out
Cause: The app listens on localhost or a hardcoded port.
Fix: Listen on 0.0.0.0 and read PORT.
Cannot find module '…/index.js' on start
Cause: There's no start script, so we fell back to index.js.
Fix: Add "start" to package.json, or set a Start command in Settings → Build.
Cannot find module '…/dist/…'
Cause: TypeScript was never compiled.
Fix: Add a build script (tsc or nest build) and start from dist/.
Unsupported engine or syntax errors
Cause: The app needs a different Node version than 22.
Fix: Set engines.node in package.json.
App crashes at boot with missing config
Cause: An env var your code needs isn't set.
Fix: Add it in Settings and redeploy. The build log shows the crash.
Still stuck? Check the deployment's build log in the dashboard, or see Troubleshooting.
Ready to deploy? Sign in with GitHub and pick your repo. No Dockerfile, no YAML.
See the full docs for custom domains, env vars, addons, and billing.