Testing, Performance & Deployment
Node.js Logging with Pino and Winston
Structured logging writes machine-readable JSON with consistent fields instead of free-text strings, so logs can be searched, filtered and alerted on. Pino is the fast default; Winston is more configurable.
What is Logging with Pino and Winston in Node.js?
Structured logging writes machine-readable JSON with consistent fields instead of free-text strings, so logs can be searched, filtered and alerted on. Pino is the fast default; Winston is more configurable.
Logging with Pino and Winston example
import pino from 'pino';
export const logger = pino({
level: process.env.LOG_LEVEL ?? 'info',
redact: ['req.headers.authorization', 'password', '*.token'],
});
// one line per request, with a correlation id
app.use((req, res, next) => {
req.id = crypto.randomUUID();
req.log = logger.child({ reqId: req.id });
next();
});
req.log.info({ jobId, userId }, 'application submitted');
req.log.error({ err }, 'failed to save application');Key points to remember
- Log objects, not interpolated strings — the fields become searchable.
- Redact tokens, passwords and personal data before they reach the log.
- A correlation id per request lets you trace one user journey across many lines.
- Write to stdout and let the platform collect it; do not manage log files in the app.
Common mistakes with Logging with Pino and Winston
- console.log in production — no levels, no structure, no redaction.
- Logging entire request bodies, which leaks credentials into log storage.
Node.js Logging with Pino and Winston— Interview Questions & FAQs
Why not just use console.log?+
It has no levels, no structure and no redaction, so you cannot filter by severity, search by field, or keep secrets out. A structured logger costs one line to set up and makes production debugging possible.
