In short
Pino is a Node logger built for speed. It writes plain JSON lines quickly and leaves pretty-printing and shipping to other tools, so logging barely slows your API.
An extremely fast, low-overhead JSON logger for Node.js — a popular modern alternative to Winston, especially for high-throughput APIs where logging overhead matters.

Think of it like this
The court stenographer
In court, the stenographer doesn't write neat paragraphs during the hearing. She types fast shorthand to keep up, and a clean transcript is prepared later. Pino works the same way: fast raw JSON now, pretty formatting later by a separate tool.
Watch it happen
From log call to log storage
1/5Your handler logs an object. Pino turns it into one JSON line with very little work.
The big ideas
What you need to know
Fast by design
Pino keeps main-thread work small and skips heavy formatting, which matters when you log on every request.
JSON lines only
One JSON object per line, with a numeric level, a timestamp and the message. Easy for log tools to parse.
Built-in redaction
redact: ['req.headers.authorization'] hides sensitive fields everywhere, so nobody can forget.
pino-http for Express
Logs each request and response with timing, and gives you req.log already carrying the request ID.
See it in code
Walk through the code
1import pino from "pino";2import pinoHttp from "pino-http";3import express from "express";4 5const logger = pino({6 level: process.env.LOG_LEVEL ?? "info",7 redact: ["req.headers.authorization", "req.headers.cookie"],8});9 10const app = express();11app.use(pinoHttp({ logger }));12 13app.get("/orders/:id", (req, res) => {14 req.log.info({ orderId: req.params.id }, "fetching order");15 res.json({ id: req.params.id });16});1/3One logger for the app. Auth headers and cookies never reach the logs.
Locally, run node dist/server.js | npx pino-pretty for readable output. In production, keep the raw JSON for your log system.
Save yourself the pain
Common mistakes
Oops
Running pino-pretty in production.
Do this instead
It adds work and turns logs into text your log tool can't parse. Keep it for local development.
Oops
Writing logger.info("order " + JSON.stringify(order)).
Do this instead
That buries fields inside a string. Pass the object first: logger.info({ order }, "order created").
Your mission
Swap in Pino
Quick check
Why does Pino recommend pretty-printing outside your app process?
Go deeper
- 1Set up Pino in an Express app and compare its output format to Winston's.
- 2Learn why Pino's performance-first design makes it popular for high-traffic services.
- 3Use `pino-pretty` for readable local development output.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.