pino-http
The fastest structured HTTP request logger for Node.js, built directly on pino and ready to drop into any http server or Express app.
Repository Health
Technical Analysis
pino-http wraps a pino logger instance around Node’s raw http.IncomingMessage/ServerResponse cycle, attaching a child logger to every request (req.log) and response (res.log) and automatically emitting a structured completion log when the response finishes, errors, or the connection closes. It benchmarks well ahead of other Node HTTP loggers because it inherits pino’s low-overhead, asynchronous JSON serialization rather than doing synchronous string formatting on the request path.
Beyond the zero-config default, it exposes a deep hook system — customLogLevel, customProps, customSuccessMessage/Object, customErrorMessage/Object, customReceivedMessage/Object, customAttributeKeys, and wrapSerializers — so teams can reshape field names, add request-scoped metadata, or change log levels per status code without forking the library or writing their own middleware from scratch. It works unmodified as vanilla Node middleware or as Express middleware, and integrates with pino’s transport and pretty-printing ecosystem out of the box.
What You Get
- Automatic request/response logging on every request, with no manual log calls required
- A child logger available as req.log / res.log, pre-bound with request context for any additional log lines a handler wants to add
- Configurable log levels per response (customLogLevel) so 4xx/5xx responses can be logged as warn/error automatically
- Custom request ID generation (genReqId) with sane integer-based defaults and support for reusing an existing x-request-id header
- Hooks to reshape the logged object and message text at each lifecycle stage (received, success, error) without losing pino’s serializer wrapping
- Drop-in compatibility with plain Node http servers and Express, plus interop with pino transports and pino-pretty for local development
Common Use Cases
- Adding production-grade structured request logging to an Express or vanilla Node HTTP API with a single middleware line
- Centralizing request/response/error logging format across a service so log aggregators (ELK, Datadog, Loki) can parse a consistent schema
- Elevating error-classed responses (4xx/5xx) to warn/error log levels automatically via customLogLevel for alerting pipelines
- Attaching request-scoped correlation IDs (genReqId) that propagate through req.log for distributed tracing correlation
- Suppressing verbose per-request bindings in high-throughput services via quietReqLogger/quietResLogger while keeping request IDs
Under The Hood
Architecture pino-http is a single-module (logger.js) middleware factory: calling the exported function normalizes options, creates or reuses a pino instance via wrapChild, and returns a closure that wires per-request state onto the Node req/res objects using two module-level Symbols (startTime, reqObject) to avoid polluting the public object shape. The request lifecycle is handled by loggingMiddleware, which attaches child loggers to req.log/res.log and registers ‘finish’/‘close’/‘error’ listeners on the response; onResFinished computes response time, resolves the log level via customLogLevel, and dispatches to either the error or success object/message providers. The separation between option normalization, logger construction, event wiring, and completion handling is clean for a file of this size, and the closure-based design (rather than a class) keeps per-request state private via symbols instead of exposed instance fields.
Tech Stack The library ships as plain CommonJS JavaScript (logger.js, deprecations.js) with hand-written TypeScript definitions (index.d.ts) validated separately via tsd rather than being compiled from TypeScript source. Runtime dependencies are minimal and pino-ecosystem-native: pino ^10 for the underlying logger, pino-std-serializers ^7 for req/res/err serialization (wrapped via wrapRequestSerializer/wrapResponseSerializer/wrapErrorSerializer), get-caller-file ^2 to resolve transport caller paths, and process-warning ^5 for deprecation warnings. Tests run on Node’s built-in test runner (node —test) with @matteo.collina/tspl for assertions, coverage via c8, linting via eslint with the neostandard shareable config, and CI wired through GitHub Actions.
Code Quality test/test.js runs to roughly 1,600 lines and exercises the option surface exhaustively — custom log levels, autoLogging.ignore, customProps as both function and object, wrapSerializers toggling, quietReqLogger/quietResLogger, and custom attribute key remapping — plus a dedicated transport-integration.js test for pino transport interop. Error handling is explicit rather than swallowed: incompatible option combinations (useLevel + customLogLevel) throw immediately rather than silently picking one. There’s no TypeScript source, but the public type surface is independently validated against real usage via tsd and ts-node in the test-types script, which catches type-definition drift that plain unit tests would miss.
API Design The public surface is a single factory function that works with zero configuration (require(‘pino-http’)()) as either a raw http listener call or Express middleware, with no adapter code needed either way. Every stage of the request lifecycle (received, success, error) has both a message hook and an object hook, letting consumers restyle log text or the structured payload independently without losing the underlying serializer wrapping. Advanced consumers get an escape hatch via the exported startTime symbol for manually correcting response-time measurement when pino-http isn’t the first middleware in the chain, and stdSerializers/pinoHttp.logger expose the underlying pino primitives directly rather than hiding them behind a facade.
Used by 12 apps in this directory
Budibase
Low Code Platforms · No Code Platforms
Build AI agents, automations, and internal apps on a single open-source platform with full self-hosting control.
Directus
CMS · Low Code Platforms
Connect any SQL database and get instant REST and GraphQL APIs, a visual management Studio, and a native MCP server for AI agents — free for most organizations.
Docmost
Productivity · Note Taking · Collaboration
Self-hosted collaborative wiki and knowledge base with real-time editing, diagrams, AI assistance, and enterprise access controls — a modern alternative to Confluence and Notion.
GrowthBook
Developer Tools · Analytics · Monitoring
Open source feature flags, A/B testing, and warehouse-native experimentation that queries your existing data infrastructure—no data movement required.
HyperDX
Developer Tools · Analytics · Monitoring
Open source observability platform that unifies logs, traces, metrics, and session replays on ClickHouse — now the core of ClickStack.
KeystoneJS
CMS · Developer Tools
The superpowered headless CMS for developers built with GraphQL and React
Mastodon
Social Media
Run your own federated social network on the open ActivityPub standard with no ads, no algorithms, and no corporate control over your community.
NocoDB
No Code Platforms · Databases · Low Code Platforms
Turn any SQL database into a collaborative no-code spreadsheet with automatic REST APIs and real-time views.
Novu
Developer Tools
Open-source communication infrastructure that connects your products and AI agents to every channel your users live on — Inbox, Email, SMS, Push, Chat, and more.