Node.js and Express course menu
How to Deploy a Node.js and Express App
Take a Node.js API to production: preparing the app (PORT, start script, engines), environment variables on the host, platform options (PaaS, containers, VPS), a Dockerfile, process managers and restarts, reverse proxies and HTTPS, databases and migrations, and a deployment checklist.
On this page
Deploying means running your app on a server that is always on and reachable from the internet. The details depend on the platform, but every Node.js deployment needs the same preparation.
Prepare the app#
1. Listen on the port the platform gives you. Hosting platforms set a PORT environment variable:
const port = Number(process.env.PORT ?? 3000);
app.listen(port, () => console.log(`Listening on ${port}`));2. Define how to start it, and which Node.js version it needs:
{
"type": "module",
"scripts": {
"start": "node src/server.js",
"test": "node --test"
},
"engines": {
"node": ">=22"
}
}3. Install only production dependencies on the server: npm ci --omit=dev installs exactly what the lock file lists, without dev tools.
4. Configuration through environment variables set in the platform's dashboard or secrets manager (database URL, JWT secret, NODE_ENV=production), never in the repository. NODE_ENV=production also makes Express and many libraries skip development-only work, such as stack traces in error pages.
5. Health check and graceful shutdown, as in Configuration, Logging and Shutdown.
Where to run it#
For a first deployment, a PaaS is the simplest: connect the Git repository, set the build command (npm ci), the start command (npm start) and environment variables, and every push deploys. Check each provider's current pricing and limits.
A Dockerfile#
Containers package the app with its exact Node.js version and dependencies, so it runs the same everywhere:
FROM node:24-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY src ./src
USER node
EXPOSE 3000
CMD ["node", "src/server.js"]node_modules
.env
.git
testCopying package*.json and running npm ci before copying the source lets Docker reuse the cached dependency layer when only your code changes. USER node runs the app without root privileges. Build and run with docker build -t shop-api . and docker run -p 3000:3000 --env-file .env shop-api. (Docker must be installed to run these commands; they are shown here as a reference.)
Keeping it running#
A crash must not take the API down for good:
- PaaS and container platforms restart crashed processes automatically.
- On a VPS, use a process manager: systemd (built into Linux) or PM2 (
pm2 start src/server.js --name shop-api), which restarts on crashes and on reboot, and collects logs. - Node runs your JavaScript on one CPU core. To use several cores, run several instances behind a load balancer (PaaS "instances", PM2 cluster mode, or containers).
Reverse proxy and HTTPS#
On a VPS, a reverse proxy such as nginx or Caddy sits in front of Node: it terminates HTTPS (with free certificates from Let's Encrypt), serves static files, compresses responses and forwards API requests to Node on a local port. PaaS platforms do this for you. Behind a proxy, set app.set("trust proxy", 1) so req.ip and req.protocol reflect the real client.
Databases in production#
- Use a managed database (managed PostgreSQL or MySQL from your cloud or PaaS provider) with automatic backups.
- Change the schema with migrations: versioned scripts applied in order, so every environment has the same tables (tools: Prisma Migrate, Drizzle Kit, Knex, node-pg-migrate).
- Keep the database in the same region as the app for low latency, and never expose it publicly.
Deployment checklist#
- Tests pass in CI before deploying.
-
PORT,NODE_ENV=productionand all secrets set on the host;.envnot committed. - Health endpoint, structured logs and error monitoring (such as Sentry) in place.
- HTTPS, Helmet, CORS limited to your front-end origins, rate limiting on auth routes.
- Graceful shutdown on SIGTERM.
- Database backups and migrations.
- A way to roll back to the previous version.
Common mistakes#
Key takeaway#
Next, build complete projects: Project: Notes API with a Database.
Finished this lesson?