NestJS Profiler

Profiler UI

A visual tour of the profiler web interface - the profiles list, the built-in tabs, and every collector panel.

Open /_profiler to browse the list of captured profiles, then click any row to open its detail view. The detail view is organized into built-in tabs (request, response, performance, logs, exceptions) plus one tab per active collector. The screenshots below come from the example application with every collector enabled.

This page is a visual tour of the panels and tabs. For the reference side — the UI endpoints, the debug response headers, the filter query parameters and how to export a profile — see Browsing profiles.

Profiles list

/_profiler opens on a sticky sidebar of views. Each entrypoint kind (HTTP, GraphQL, Commands, RabbitMQ) gets its own page under a Profiling group, and every global-scope collector (Config, Routes, Schemas) is a view of its own — each badged with its count. Only the active view is rendered; it is picked server-side from a ?view= link, so there is no client-side routing.

Every list carries its own filter bar and is filtered independently: the universal filters (search, duration, performance tag — slow / N+1 / chatty / large payload / no rows — plus an Exception select and an Errors checkbox), the HTTP-status filters (status, status class) shown only on the kinds that carry an HTTP response (HTTP, GraphQL), and filters specific to that kind (e.g. HTTP method, RabbitMQ delivery/exchange/handler). A kind hides a universal filter that is redundant for it — the Commands list has no Errors checkbox, its Status filter already asking the same question.

Profiler home — the sidebar of views with count badges, the process-heap trend and the HTTP list narrowed by the method filter

GraphQL operations

Requires @eleven-labs/nest-profiler-graphql - see the GraphQL support section in Getting started.

GraphQL operations get their own GraphQL view in the sidebar (separate from REST requests), each row showing the operation type (QUERY, MUTATION, or SUBSCRIPTION) and the operation or field name. Its filter bar adds an Operation filter to narrow the list by operation type.

GraphQL view listing QUERY and MUTATION operations alongside their status

Opening an operation lands on its dedicated GraphQL detail tab, displaying:

  • Operation type badge (Query / Mutation / Subscription)
  • Operation name if present in the request
  • Field name - the entry-point resolver
  • Query - syntax-highlighted GraphQL document
  • Variables - the variables object, syntax-highlighted as JSON
  • Response - the { data, errors } envelope returned to the client
  • Request headers - the underlying HTTP headers

GraphQL detail tab with operation type, name, syntax-highlighted query and variables (Query)

GraphQL detail tab for a Mutation with input variables

GraphQL-level errors (schema validation failures, resolver errors returned in response.body.errors) appear in the Exceptions tab with an amber GraphQLError badge, visually distinct from NestJS runtime exceptions which use a red badge. Since GraphQL names every error GraphQLError, its extensions.code is shown alongside — BAD_REQUEST here — and that code is what the Exception filter lists and what decides whether the operation counts as an error.

Exceptions tab showing an amber GraphQLError badge with its BAD_REQUEST code, validation message and location

Built-in tabs

The Request tab details the method, URL, headers, and collected body.

Request tab showing a POST create with its method, headers and JSON request body

The Response tab shows the status, response headers, and body returned by the handler.

Response tab showing status, headers, and JSON body

The Performance tab groups request duration, memory, and timestamps.

Performance tab with duration, memory, and request timeline

The Logs tab lists entries captured through createProfilerLogger(). Each row shows the message first - with structured payloads rendered as a JSON block under it - then the logger context name. See the Log capture page for the supported logger conventions.

Logs tab showing messages with context names and a structured JSON payload

The Exceptions tab lists what the profile captured, each with its message and stack trace — here the InternalServerErrorException behind a 500. A captured exception is not automatically an error, though: a BadRequestException answering 400 means the application did its job, so it appears here and under the Exception filter, but not under the Errors checkbox. See What counts as an error.

Exceptions tab displaying a captured InternalServerErrorException with its stack trace

Collectors

The Timeline collector displays spans created with startSpan() as synchronized bars.

Timeline tab showing slow.step.fetch, slow.step.process, and slow.step.serialize spans

The Database collector shows SQL queries (TypeORM or MikroORM) with their SQL type and duration, plus a metadata line per query — rows affected/returned and the connection, rendered as a chip (localhost:5432 / shop). The panel header sums the rows read.

Database tab showing a profiled SQL SELECT query

A zero-row UPDATE/DELETE is a silent failure — the query ran but changed nothing (a mismatched WHERE). It is highlighted, its 0 rows count turns amber, and the zero-rows tag lights the Performance banner and colours the Database tab:

Database tab of a PATCH that affected 0 rows, with a "Performance — 1 issue detected" banner reading "No rows" and the query showing 0 rows

The MongoDB collector (requires @eleven-labs/nest-profiler-mongoose) shows Mongoose queries and aggregations with their operation, collection, duration, result/affected count, and connection.

MongoDB tab showing a profiled Mongoose query with collection, operation and duration

The HTTP Client collector shows outgoing requests triggered by HttpService.

HTTP Client tab showing a GET call to JSONPlaceholder

The Cache collector shows GET_HIT, GET_MISS, SET operations and the hit rate.

Cache tab showing a GET_HIT and a 100 percent hit rate

The Command collector (requires @eleven-labs/nest-profiler-commander) profiles nest-commander CLI runs. With file storage, commands get their own Commands view — a CLI badge and the command line in place of the URL, with a Status filter for successful vs failed runs — and the Command tab details the command name, arguments, options, and exit code.

Command tab showing a profiled nest-commander run with arguments, options and exit code

The RabbitMQ collector (requires @eleven-labs/nest-profiler-rabbitmq) profiles messages consumed via @RabbitSubscribe. Each delivery becomes its own profile: a dedicated RabbitMQ view, and a Message detail tab showing the exchange, routing key, handler, delivery metadata and JSON payload.

RabbitMQ view showing a consumed review.created delivery and its filters

Message tab showing a consumed review.created delivery with exchange, routing key, handler and JSON payload

The Security collector shows the authenticated user, roles, and decoded JWT claims.

Security tab showing an authenticated demo_user with the admin role

The Validator collector shows validated DTOs and failing class-validator constraints.

Validator tab showing two validation violations on CreatePostDto

The Config collector is global — it describes the application, not one request — so it is a sidebar view of its own, exposing the runtime and the flattened configuration with secrets masked.

Config view showing the runtime tiles and the flattened app/database keys with database.password masked

Powered & maintained by

On this page