Express.js Logging Best Practices for Production
Good logging is the difference between debugging a production issue in minutes versus hours. Here's how to set up Express logging properly.
Use Structured Logging
Ditch console.log for structured JSON logs with Winston:
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.Console(),
],
});Add Request Correlation IDs
Trace requests across services with unique IDs:
const { v4: uuidv4 } = require('uuid');
app.use((req, res, next) => {
req.id = req.headers['x-request-id'] || uuidv4();
res.setHeader('x-request-id', req.id);
next();
});
// Use in route handlers
app.get('/api/orders', async (req, res) => {
logger.info('Fetching orders', { requestId: req.id, userId: req.user.id });
// ...
});Filter Sensitive Data
Never log passwords, tokens, or PII:
const sanitize = (obj) => {
const redacted = { ...obj };
const sensitive = ['password', 'token', 'authorization', 'ssn', 'creditCard'];
for (const key of Object.keys(redacted)) {
if (sensitive.includes(key.toLowerCase())) {
redacted[key] = '[REDACTED]';
}
}
return redacted;
};Log Levels Guide
- error — something broke, needs immediate attention
- warn — something unexpected but handled (retry succeeded, fallback used)
- info — significant business events (user signup, order placed)
- debug — detailed diagnostic data (disabled in production)
Request Logging Middleware
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
logger.info('request completed', {
method: req.method,
path: req.originalUrl,
status: res.statusCode,
duration: Date.now() - start,
requestId: req.id,
});
});
next();
});Pair structured logs with Bugsly's error tracking to correlate log entries with specific exceptions, giving you the full context when investigating production issues.
Try Bugsly Free
AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.
Get Started FreeRelated Articles
How to Catch Broken Releases Before Users Report Them
A practical guide to using error tracking, release tagging, and automated alerts to detect broken deploys within minutes — not after user complaints.
Read moreReact Logging Best Practices for Production
Implement effective logging in React applications with structured client-side logging, error boundaries, and remote log aggregation strategies.
Read moreRemix Performance Monitoring Best Practices
Monitor Remix application performance with loader timing, action profiling, streaming metrics, and server-side rendering optimization.
Read moreGo Error Handling Patterns for Production Code
Learn idiomatic Go error handling patterns including error wrapping, custom types, sentinel errors, and structured error reporting.
Read more