{"id":16177,"library":"pino-http","title":"Pino HTTP Logger Middleware","description":"pino-http is a high-speed HTTP logger middleware designed for Node.js applications, leveraging the highly performant Pino logging library. It focuses on providing structured JSON logs for HTTP requests and responses with minimal overhead, making it ideal for high-throughput microservices and APIs. The package is currently at version 11.0.0 and follows a release cadence that often aligns with major updates to its underlying `pino` dependency, typically seeing several minor/patch releases throughout the year. Its primary differentiator is its exceptional performance compared to other HTTP loggers, achieved by deferring heavy log processing. It provides extensive customization options for log levels, request ID generation, and structured log data.","status":"active","version":"11.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/pinojs/pino-http","tags":["javascript","typescript"],"install":[{"cmd":"npm install pino-http","lang":"bash","label":"npm"},{"cmd":"yarn add pino-http","lang":"bash","label":"yarn"},{"cmd":"pnpm add pino-http","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core logging library that pino-http is built upon for high-speed, structured logging. Version compatibility is critical for major updates.","package":"pino","optional":false},{"reason":"Used for human-readable, colored output during development. Not a runtime dependency for production applications but essential for local debugging.","package":"pino-pretty","optional":true}],"imports":[{"note":"The default export is a factory function. In CommonJS, `require('pino-http')()` is typically used. For ESM, `import pinoHttp from 'pino-http';` or `import createPinoHttp from 'pino-http';` followed by `pinoHttp()` or `createPinoHttp()` to instantiate.","wrong":"const pinoHttp = require('pino-http');\n// Requires a function call to initialize: const pinoHttp = require('pino-http')();","symbol":"pinoHttp","correct":"import pinoHttp from 'pino-http';\n// or\nimport createPinoHttp from 'pino-http';"},{"note":"Type import for the instantiated logger function provided by pino-http. Use for explicit TypeScript typing.","symbol":"PinoHttpLogger","correct":"import type { PinoHttpLogger } from 'pino-http';"},{"note":"The `req.log` property injected by pino-http is a standard Pino logger instance. For full type coverage, import `Logger` from 'pino' and alias it if necessary.","symbol":"PinoLogger","correct":"import type { Logger as PinoLogger } from 'pino';"}],"quickstart":{"code":"import http from 'node:http';\nimport pinoHttp from 'pino-http';\nimport pino from 'pino';\n\n// Create a base Pino logger (optional, pino-http can create one internally)\nconst baseLogger = pino({\n  level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',\n  transport: {\n    target: 'pino-pretty',\n    options: {\n      colorize: true\n    }\n  }\n});\n\nconst loggerMiddleware = pinoHttp({\n  logger: baseLogger,\n  genReqId: function (req) {\n    // Generate a unique request ID for better traceability\n    return req.headers['x-request-id'] || Math.random().toString(36).substring(2, 15);\n  },\n  customLogLevel: function (req, res, err) {\n    if (res.statusCode >= 400 && res.statusCode < 500) return 'warn';\n    if (res.statusCode >= 500 || err) return 'error';\n    return 'info';\n  }\n});\n\nconst server = http.createServer((req, res) => {\n  loggerMiddleware(req, res);\n\n  req.log.info({ url: req.url, method: req.method }, 'Incoming request');\n\n  if (req.url === '/error') {\n    req.log.error('Simulating an error');\n    res.statusCode = 500;\n    res.end('Internal Server Error');\n    return;\n  }\n\n  res.end('Hello world!');\n});\n\nconst PORT = process.env.PORT || 3000;\nserver.listen(PORT, () => {\n  baseLogger.info(`Server listening on port ${PORT}`);\n});\n\n// To run: node --loader ts-node/esm your-file.ts (if using ts-node and ESM)\n// or: node your-file.js","lang":"typescript","description":"This quickstart demonstrates how to set up `pino-http` with a custom base logger, request ID generation, and dynamic log level based on response status. It includes a basic HTTP server, showcasing how `req.log` is injected for contextual logging and how to use `pino-pretty` for development output."},"warnings":[{"fix":"Upgrade Node.js to version 20 or higher. If upgrading is not immediately possible, pin pino-http to a `^10.0.0` version.","message":"pino-http v11.x, which updates to pino v10.x, officially drops support for Node.js 18. Users on Node.js 18 or older should use pino-http v10.x or upgrade their Node.js version.","severity":"breaking","affected_versions":">=11.0.0"},{"fix":"Choose either `customLogLevel` (a function for dynamic level selection) or `useLevel` (a static level string) but not both.","message":"The `customLogLevel` and `useLevel` options are mutually exclusive. Providing both will result in undefined behavior or one overriding the other in an unexpected way.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Set `autoLogging: false` to disable automatic logging entirely, or `autoLogging: { ignore: (req) => req.url === '/healthz' }` for conditional exclusion.","message":"By default, `pino-http` automatically logs a 'request completed' or 'request errored' message. To disable this, set `autoLogging: false` in the options. To selectively ignore certain requests from being logged, use `autoLogging.ignore`.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Carefully consider what data is serialized. Use Pino's redaction capabilities or custom serializers to remove sensitive information. Avoid logging large request bodies unless absolutely necessary.","message":"Logging sensitive request bodies or adding extensive custom serializers can negatively impact performance and introduce security risks by exposing private data.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Provide a custom `genReqId` function that generates truly unique IDs, e.g., using `uuid` or a tracing ID from upstream services (`req.headers['x-request-id']`).","message":"The default `genReqId` (request ID generator) uses an integer counter which might not be unique across multiple application instances or restarts. For robust production environments, a more unique ID generation strategy is recommended.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Install `pino-pretty` (`npm i -D pino-pretty`) and configure Pino's `transport` option, typically only for development environments, to use it.","cause":"`pino-pretty` is not installed or not used in the transport configuration.","error":"logs are not formatted/colored, they are raw JSON"},{"fix":"For CommonJS, ensure `const pinoHttp = require('pino-http')();` (with `()`). For ESM, use `import pinoHttp from 'pino-http';` then call it as `pinoHttp();`.","cause":"Incorrect CommonJS `require` usage or improper ESM import for the factory function.","error":"Error: Cannot find module 'pino-http' or type errors related to `pinoHttp` not being a function"},{"fix":"Ensure `loggerMiddleware(req, res);` (where `loggerMiddleware` is your `pinoHttp()` instance) is called early in your HTTP request handling chain, typically as the first middleware in frameworks like Express.","cause":"`pino-http` middleware function was not called or executed for the given request/response cycle, or was called incorrectly.","error":"TypeError: Cannot read properties of undefined (reading 'info') on req.log"},{"fix":"Ensure that custom log levels are correctly defined in your Pino configuration via the `customLevels` option and that the `useLevel` or `customLogLevel` functions return one of these defined levels or standard Pino levels.","cause":"Using a custom log level string that is not recognized by Pino's default types or declared in your custom levels.","error":"Argument of type 'string' is not assignable to parameter of type 'PinoLogLevel'."}],"ecosystem":"npm"}