Oliver White
4 May 2026 · 6 min read
A Sentry stack trace tells you what broke. It does not tell you which request, what the input was, how long the request had been running, or what happened immediately before the failure. Structured logging with a thread-through request ID fills that gap. Here is the full pattern for Next.js API routes.
console.log in a production API route produces unstructured text. It's not searchable by field, not parseable by log aggregators, and doesn't capture structured metadata like request ID, user ID, or duration. When you have multiple concurrent requests, log lines from different requests interleave with no way to correlate them.
console.log
pino structured JSON
Include requestId in the response as an X-Request-Id header. This lets you correlate a client-side error (the user screenshots the browser console) with the server-side log entry — no guessing which of 50 concurrent requests failed.
| Field | Type | Example | Purpose |
|---|---|---|---|
| requestId | string | req_1715012345678_abc1234 | Correlate all logs for one request |
| level | string | info / error / warn | Filter by severity |
| msg | string | vote request complete | Human-readable event |
| durationMs | number | 42 | Performance monitoring |
| success | boolean | true | Outcome tracking |
| errorCode | string | null | ALREADY_VOTED | Error classification |
| time | number | 1715012345678 | Timestamp (Unix ms) |
Built with this methodology
A Sentry stack trace tells you what broke. A structured pino log with a request ID tells you everything else: which request, what input, how long it ran, what preceded the failure. Here is how to build that in Next.js API routes.
From the build log