Most Node.js REST API tutorials show you how to get an endpoint returning JSON. Almost none of them show you how to make it production-ready. This guide covers the non-negotiable items: authentication, rate limiting, input validation, error handling, and structured logging — the things that get you paged at 3 AM if you skip them.
Project Structure
Authentication with JWT
Use short-lived access tokens (15 minutes) paired with refresh tokens stored in httpOnly cookies. Never store JWTs in localStorage — XSS attacks can exfiltrate them.
Input Validation with Zod
Validate every incoming request body. Trust nothing from the client. Zod provides TypeScript-native validation with excellent error messages:
Rate Limiting
Structured Error Handling
A consistent error format makes debugging and client-side error handling dramatically easier. Define a base error class and a global error handler:
Structured Logging with Pino
Production Checklist
- Helmet.js: sets security headers (CSP, HSTS, X-Frame-Options) in one line
- CORS: configure explicitly — never use cors() with no options in production
- Compression: gzip responses with the compression middleware
- Health endpoint: GET /health returns 200 with DB connectivity check — used by load balancers
- Graceful shutdown: handle SIGTERM, close server and DB connections cleanly before exit
- Environment variables: use dotenv for local dev, never commit .env files
- Security: run npm audit weekly; use Snyk or GitHub Dependabot for automated alerts
- Load testing: run k6 or Artillery before launch — find your breaking point before users do