NIXKnight/demo_express_js_app
Demo Express.js Application
A production-ready Express.js application featuring PM2 cluster mode, structured logging, security middleware, and comprehensive monitoring capabilities.
Features
- Express.js Framework - Fast, unopinionated, minimalist web framework
- PM2 Cluster Mode - Multi-process load balancing across all CPU cores
- Structured Logging - Pino logger with pretty-printing in development, JSON in production
- Security Middleware - Helmet for security headers, CORS support, rate limiting
- Performance Optimization - Response compression, optimized middleware stack
- Health Monitoring - Health check endpoint with uptime and environment info
- Environment Configuration - dotenv for environment variable management
- Development Tools - Nodemon for hot-reloading during development
Architecture Overview
Middleware Stack
The application uses a carefully ordered middleware stack:
- dotenv - Loads environment variables
- Helmet - Security headers (CSP disabled in development)
- CORS - Cross-Origin Resource Sharing support
- Compression - Gzip/deflate response compression
- Pino-HTTP - Structured request/response logging
- Body Parsers - JSON and URL-encoded body parsing
- Cookie Parser - Cookie parsing middleware
- Static Files - Serves files from public/ directory
- Rate Limiting - Applied to /api/* routes
- Application Routes - Custom route handlers
- Error Handler - Comprehensive error handling with logging
Logging System
- Development: Pretty-printed, colorized logs with pino-pretty
- Production: Structured JSON logs for aggregation and analysis
- Request Logging: Automatic HTTP request/response logging
- Error Context: Errors logged with full request context
PM2 Clustering
- Cluster Mode: Spawns one process per CPU core
- Load Balancing: Built-in round-robin load balancing
- Auto-Restart: Automatic restart on crash or memory limit
- Graceful Shutdown: 5-second grace period for in-flight requests
- Log Management: Centralized log files in logs/ directory
Prerequisites
- Node.js: v16.x or higher recommended
- npm: v7.x or higher
- PM2: Install globally with
npm install -g pm2(for production)
Installation
- Clone the repository:
git clone git@github.com:NIXKnight/demo_express_js_app.git
cd demo_express_js_app- Install dependencies:
npm install- Configure environment variables:
cp .env.example .env
# Edit .env with your configurationDevelopment
Start Development Server
Hot-reload development server with pretty logs:
npm run devThe server will start on port 3000 (or PORT from .env) and automatically restart on file changes.
PM2 Commands
Start with PM2 in cluster mode:
npm run pm2:startView PM2 status:
npm run pm2:statusView logs:
npm run pm2:logsMonitor in real-time:
npm run pm2:monitRestart application:
npm run pm2:restartStop application:
npm run pm2:stopRemove from PM2:
npm run pm2:deleteEnvironment Variables
Create a .env file in the root directory (use .env.example as template):
| Variable | Description | Default |
|---|---|---|
NODE_ENV |
Application environment (development/production) | development |
PORT |
Server port | 3000 |
LOG_LEVEL |
Logging level (trace/debug/info/warn/error/fatal) | info (prod), debug (dev) |
RATE_LIMIT_WINDOW_MS |
Rate limit window in milliseconds | 900000 (15 min) |
RATE_LIMIT_MAX_REQUESTS |
Max requests per window | 100 |
CORS_ORIGIN |
Allowed CORS origins (* for all) | * |
Deployment
Production Deployment with PM2
- Ensure NODE_ENV is set to production:
export NODE_ENV=production- Start with PM2:
npm run pm2:start- Configure PM2 to start on system boot:
pm2 startup
pm2 save- Monitor application:
pm2 monitProduction Checklist
- Set NODE_ENV=production
- Configure .env with production values
- Set appropriate CORS_ORIGIN (not *)
- Configure LOG_LEVEL to info or warn
- Set up log rotation
- Configure reverse proxy (nginx/Apache)
- Set up SSL/TLS certificates
- Configure firewall rules
- Set up monitoring and alerting
Project Structure
demo_express_js_app/
├── app.js # Express application setup
├── bin/
│ └── www # Server bootstrap
├── ecosystem.config.js # PM2 configuration
├── logs/ # PM2 logs directory
│ ├── pm2-error.log
│ └── pm2-out.log
├── package.json # Dependencies and scripts
├── public/ # Static assets
│ ├── images/
│ ├── javascripts/
│ └── stylesheets/
├── routes/ # Route handlers
│ ├── index.js
│ └── users.js
├── utils/ # Utility modules
│ └── logger.js # Pino logger configuration
├── views/ # EJS templates
│ ├── error.ejs
│ └── index.ejs
├── .env.example # Environment variable template
├── .gitignore # Git ignore patterns
└── README.md # This file
API Endpoints
Health Check
GET /health
Returns application health status:
{
"status": "ok",
"timestamp": "2025-10-13T19:30:00.000Z",
"uptime": 123.456,
"environment": "production"
}Default Routes
GET /- Home pageGET /users- Users route
Security Features
Helmet
Helmet sets various HTTP headers for security:
- Content Security Policy (disabled in development)
- X-DNS-Prefetch-Control
- X-Frame-Options
- X-Content-Type-Options
- Strict-Transport-Security
- X-Download-Options
- X-Permitted-Cross-Domain-Policies
Rate Limiting
API routes (/api/*) are protected with rate limiting:
- Default: 100 requests per 15 minutes per IP
- Returns 429 status when limit exceeded
- Configurable via environment variables
Additional Security
x-powered-byheader disabled- Trust proxy enabled for proper IP detection
- Cookie parsing with security considerations
- CORS configurable per environment
Performance Considerations
Clustering
PM2 cluster mode provides:
- Horizontal Scaling: Multiple processes handle requests
- Load Distribution: Built-in round-robin load balancing
- CPU Utilization: Uses all available CPU cores
- Zero Downtime: Rolling restarts with pm2 reload
Compression
Response compression reduces bandwidth:
- Gzip/deflate compression for text responses
- Automatic content negotiation
- Threshold-based compression
Memory Management
- Memory limit: 1GB per process (configurable in ecosystem.config.js)
- Auto-restart on memory threshold
- Graceful shutdown prevents memory leaks
Troubleshooting
Application Won't Start
- Check Node.js version:
node --version(requires v16+) - Reinstall dependencies:
rm -rf node_modules package-lock.json && npm install - Check port availability:
lsof -i :3000 - Review logs:
npm run pm2:logsor check logs/ directory
PM2 Issues
- Check PM2 status:
npm run pm2:status - View detailed logs:
pm2 logs demo-express-js-app --lines 100 - Restart application:
npm run pm2:restart - Delete and restart:
npm run pm2:delete && npm run pm2:start
Memory Leaks
- Monitor memory usage:
npm run pm2:monit - Check for memory-intensive operations
- Review log aggregation settings
- Adjust max_memory_restart in ecosystem.config.js
High CPU Usage
- Check number of PM2 instances:
npm run pm2:status - Review cluster mode configuration
- Check for infinite loops or blocking operations
- Use profiling tools:
node --prof ./bin/www
Log Issues
- Check log directory permissions:
ls -la logs/ - Verify LOG_LEVEL in .env
- Review pino configuration in utils/logger.js
- Check disk space:
df -h