Powered & maintained by Eleven Labs
A Symfony Web Profiler-inspired toolkit for NestJS applications. Each profiled execution receives a unique token, and a rich panel UI at /_profiler lets you inspect request data, logs, exceptions, performance spans, and much more — in real time.
The ecosystem is built around an extensible collector architecture: the core package provides the profiler engine, storage, and UI, while optional sub-packages each add a dedicated panel as a self-contained NestJS module.
Each package is a self-contained NestJS module with its own README:
@eleven-labs/nest-profiler— Core + Timeline panel@eleven-labs/nest-profiler-typeorm— Database panel (TypeORM)@eleven-labs/nest-profiler-mikro-orm— Database panel (MikroORM)@eleven-labs/nest-profiler-http— HTTP Client panel (ships axios wiring, bring your own client)@eleven-labs/nest-profiler-cache— Cache panel@eleven-labs/nest-profiler-auth— Security panel@eleven-labs/nest-profiler-config— Config panel@eleven-labs/nest-profiler-routes— Routes panel (REST + GraphQL / RabbitMQ / CLI)@eleven-labs/nest-profiler-mongoose— Database (NoSQL) panel@eleven-labs/nest-profiler-validator— Validator panel@eleven-labs/nest-profiler-graphql— GraphQL panel (Apollo / Mercurius / graphql-yoga)@eleven-labs/nest-profiler-commander— Command panel (CLI / nest-commander)@eleven-labs/nest-profiler-rabbitmq— RabbitMQ panel (messages consumed via@RabbitSubscribe)
Full guides and API reference live on the documentation site (pnpm docs:dev, then http://localhost:3002).
Requirements: Node.js 22+, pnpm 10+
pnpm install # install dependencies
pnpm build # build all packages
pnpm test:cov # run the test suite with coverage
pnpm docs:dev # serve the documentation site at http://localhost:3002To try the profiler against a real app, start the databases and the demo API, then open http://localhost:3000/_profiler:
pnpm docker:up # Postgres + MongoDB + RabbitMQ (runs in the background)
pnpm example:devPackages are published to the public npm registry — install them like any other dependency, no authentication required. There is no stable release yet, so every @eleven-labs/nest-profiler* package must be installed with the @alpha dist-tag (@latest resolves to nothing):
pnpm add @eleven-labs/nest-profiler@alpha nestjs-clsPrefer the profiler in
devDependenciesonly, with zero production footprint? Install it withpnpm add -Dand use the dev-entry split instead of a runtime gate.
import { ProfilerModule } from '@eleven-labs/nest-profiler';
@Module({
imports: [
ProfilerModule.forRoot({
isGlobal: true,
enabled: process.env.NODE_ENV !== 'production',
}),
],
})
export class AppModule {}Add optional collectors in their respective feature modules:
pnpm add @eleven-labs/nest-profiler-typeorm@alphaimport { TypeOrmCollectorModule } from '@eleven-labs/nest-profiler-typeorm';
@Module({
imports: [TypeOrmCollectorModule.forRoot({ slowQueryThreshold: 50 })],
})
export class ProductsModule {}Prefer to have your coding agent do the wiring? Installable agent skills teach Claude Code, Cursor, Codex and others how to set up the profiler in your own app — introspecting the project, choosing an enable strategy, and adding the collectors that match your stack:
npx skills add eleven-labs/nest-profilerThen ask your agent to "set up nest-profiler in this app". See skills/ for the full list.
A pnpm + Turbo monorepo. Publishable packages live under packages/; everything else supports them.
packages/
nest-profiler/ core profiler engine, storage, and UI
nest-profiler-*/ optional collectors (typeorm, mikro-orm, axios, cache, auth, config, mongoose, validator, graphql, commander, rabbitmq)
configs/ shared @repo/* tooling presets (eslint, jest, prettier, typescript)
examples/
api/ NestJS demo app with all collectors enabled
docs/ Fumadocs documentation site
skills/ installable agent skills for consumers (npx skills)
scripts/ repository automation and release helpers
The profiler is a thin pipeline wired into the standard NestJS request lifecycle, designed so that collectors stay decoupled from the core and disabling the profiler costs almost nothing.
The profiler has two layers:
- Active — mounts the middleware, the global interceptor, the
/_profilercontroller, the collector registry and storage. - Inert — registers only
ProfilerService, backed by the zero-dependencyNoopProfilerService, so application code that injectsProfilerServicedirectly (startSpan,getCurrentToken) keeps working with zero overhead.
The recommended way to toggle the profiler is ConditionalModule.registerWhen
on the active module — it is never loaded when profiling is off. Log capture keeps
working regardless: createProfilerLogger is DI-free and a transparent pass-through
when off. Only if application code injects ProfilerService directly do you add
ProfilerNoopModule as the off-path fallback (the inert layer above). Turn the
profiler on in development and off in production. A top-level enabled flag is also
supported as an alternative, documented once in the
Configuration guide.
request
│
▼
ProfilerMiddleware ── creates a Profile (unique token), stores it in the
│ request-scoped CLS context (nestjs-cls)
▼
route handler ──────── your code; collectors append entries into the active
│ Profile via CLS (SQL queries, HTTP calls, cache ops…)
▼
ProfilerInterceptor ── finalizes timing, runs CollectorRegistry.collectAll(),
│ lets context adapters enrich the Profile, persists it,
│ and injects the toolbar into HTML responses
▼
ProfilerStorageService → storage adapter (memory, file, or SQLite)
│
▼
ProfilerController ─── serves the UI at /_profiler (list / detail / data),
protected by ProfilerGuard
The shared CLS context (nestjs-cls) is the backbone: the middleware puts
the Profile there, and everything downstream — collectors, the logger adapter,
ProfilerService — reads it back without threading the profile through method
signatures.
Each optional @eleven-labs/nest-profiler-* package is a self-contained NestJS
module that does two things:
- Patches its host library (the TypeORM driver, the MikroORM logger, axios
interceptors, the cache manager,
ValidationPipe…) to append entries to the active profile. Patches are idempotent (__profilerPatched) so re-init never double-instruments. - Exposes a panel via a provider annotated with
@ProfilerCollector(). TheCollectorRegistryauto-discovers these through Nest'sDiscoveryService— no manual registration — and calls eachcollect()to build its panel data.
This is the extension seam: a custom collector is just a provider implementing
IProfilerCollector. See Custom collectors.
Protocols other than HTTP (GraphQL, gRPC, WebSockets…) are supported through
IContextAdapter: an adapter recovers and enriches the profile for its context
type, and the interceptor delegates to it automatically once it is registered from
your module's onModuleInit via ProfilerCoreService.registerContextAdapter(). See
Custom protocol adapters.
Run a task across every package via Turbo:
pnpm lint # eslint
pnpm typecheck # tsc --noEmit
pnpm test # run unit tests
pnpm test:cov # run tests with coverage (enforces the 90% threshold)
pnpm build # build all packages
pnpm docs:dev # serve the docs site
pnpm docker:up # start Postgres + MongoDB + RabbitMQ for the example (docker:down to stop)
pnpm attw # check published type resolution (Are the Types Wrong?)
pnpm changeset # record a version bumpTarget a single package with --filter:
pnpm --filter @eleven-labs/nest-profiler test:cov
pnpm --filter @eleven-labs/nest-profiler-typeorm buildPackages are versioned with Changesets and released from CI to the public npm registry. The versioning policy, the stable release flow, and the alpha/beta prerelease runbook live in MAINTAINERS.md.












