Your API works on localhost. The final step is making it work for everyone, reliably, on the public internet. This lesson walks through preparing an Express app for production, deploying it to a modern host, and the security and performance practices that separate hobby projects from professional services.
Before deploying, make sure the app itself is production-shaped:
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
}const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log('Listening on ' + PORT));Three middleware packages give you enormous protection for three lines of code:
npm install helmet cors express-rate-limit compressionconst helmet = require('helmet');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const compression = require('compression');
app.use(helmet()); // security headers
app.use(cors({ origin: process.env.CLIENT_URL })); // explicit allowed origin
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 200 }));
app.use(compression()); // gzip responseshelmet sets headers that block clickjacking and MIME sniffing. cors should name your real frontend origin rather than allowing every site. Rate limiting blunts brute-force and scraping. compression shrinks JSON and HTML responses dramatically.
Hosts send SIGTERM before restarting your process. Finish in-flight requests instead of dropping them:
const server = app.listen(PORT);
process.on('SIGTERM', () => {
server.close(() => {
console.log('Server closed cleanly');
process.exit(0);
});
});For a typical flow on Render: push your repo, create a Web Service, set the build command to npm install, the start command to npm start, add MONGODB_URI and JWT_SECRET as environment variables, and deploy. Your MongoDB should live in Atlas so the database and app scale independently.
On a VPS, a crash would take your site down until you notice. PM2 restarts the process, balances across CPU cores, and survives reboots:
npm install -g pm2
pm2 start index.js -i max --name my-api
pm2 save && pm2 startupPlatform hosts like Render handle restarts for you, which is a big part of what you pay for.
You cannot fix what you cannot see. At minimum, log every request with morgan in combined mode, add a /health endpoint returning 200 for uptime monitors, and send crash reports somewhere persistent. Structured JSON logging with pino is the professional upgrade when logs need searching.
Congratulations! You have completed the Express.js series. Revisit the REST API lesson and try shipping that project end to end. As a next step, explore testing Express apps with Jest and Supertest.