Pino Logging

Structured Logs Out of the Box

Pino Logging

Fastify uses Pino — a fast structured JSON logger with per-request child loggers and a pino-pretty transport for development.

4 min read Level 2/5 #fastify#logging#pino
What you'll learn
  • Enable the logger via Fastify factory options
  • Use app.log and request.log
  • Switch to pretty output during development

Fastify integrates Pino directly, so every app gets fast structured logging without extra setup.

Enabling the Logger

const app = Fastify({
  logger: {
    level: process.env.LOG_LEVEL ?? 'info',
  },
});

By default each request logs incoming request and request completed lines with reqId, method, URL, status, and response time.

App and Request Loggers

app.log.info({ version: '1.0.0' }, 'booting');

app.post('/login', async (req) => {
  req.log.info({ email: req.body.email }, 'login attempt');
  return { ok: true };
});

request.log is a child logger pre-bound with the reqId, so every line tied to that request is correlated.

Pretty Output in Dev

npm i -D pino-pretty
const app = Fastify({
  logger: {
    level: 'debug',
    transport:
      process.env.NODE_ENV !== 'production'
        ? { target: 'pino-pretty', options: { colorize: true } }
        : undefined,
  },
});

Production keeps raw JSON so log aggregators (Loki, Datadog, CloudWatch) can index every field.

Per-Route Log Level

You can tune verbosity for a single noisy route:

app.get('/healthz', { logLevel: 'warn' }, async () => ({ ok: true }));
Configuration & dotenv →