nest-profiler-graphql
Profile GraphQL queries and mutations across Apollo, Mercurius and yoga.
@eleven-labs/nest-profiler-graphql
@eleven-labs/nest-profiler-graphql captures GraphQL queries and mutations and displays them in their own GraphQL sidebar view, each with a dedicated GraphQL detail tab (operation, query, variables and response).


Installation
pnpm add @eleven-labs/nest-profiler-graphql@alphaThere is no stable release yet — install every
@eleven-labs/nest-profiler*package with the@alphadist-tag (@latestresolves to nothing).
Setup
Import GraphQLCollectorModule alongside ProfilerModule in your application module.
Apollo Server (Express or Fastify)
import { ConditionalModule } from '@nestjs/config';
import { GraphQLCollectorModule } from '@eleven-labs/nest-profiler-graphql';
const isProfilerEnabled = (env: NodeJS.ProcessEnv) => env['PROFILER_ENABLED'] === 'true';
@Module({
imports: [
ConditionalModule.registerWhen(GraphQLCollectorModule.forRoot(), isProfilerEnabled),
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
// Required — exposes the Express/Fastify request so the profiler can
// store and recover the profile across the async context boundary.
context: ({ req }) => ({ req }),
}),
],
})
export class AppModule {}Mercurius (Fastify)
(GraphQLCollectorModule.forRoot(),
GraphQLModule.forRoot<MercuriusDriverConfig>({
driver: MercuriusDriver,
autoSchemaFile: true,
// Mercurius uses `request` instead of `req`
context: ({ request }) => ({ request }),
}));graphql-yoga (Express or Fastify)
(GraphQLCollectorModule.forRoot(),
GraphQLModule.forRoot<YogaDriverConfig>({
driver: YogaDriver,
autoSchemaFile: true,
context: ({ req }) => ({ req }),
}));Enabling and disabling
Enabling / disabling — gate the collector with
ConditionalModule.registerWhen(..., isProfilerEnabled)as shown, so it loads only whenPROFILER_ENABLEDis on. Wire the coreProfilerModuleonce at the root — the recommended setup bundles the root-level profiler modules into a singleProfilingModulebehind aConditionalModulegate (see Enabling and disabling the profiler and the example app). A top-levelenabledoption is also supported as an alternative.
Ignoring playground and introspection requests
The playground and introspection requests are profiled by default. Use the
ignoreRequest option of ProfilerModule together with the pre-built filters
from this package to exclude them:
import { ProfilerModule, combineFilters } from '@eleven-labs/nest-profiler';
import {
GraphQLCollectorModule,
ignoreGraphQLPlayground,
ignoreGraphQLIntrospection,
} from '@eleven-labs/nest-profiler-graphql';
ProfilerModule.forRoot({
isGlobal: true,
ignoreRequest: combineFilters(ignoreGraphQLPlayground, ignoreGraphQLIntrospection),
}),
GraphQLCollectorModule.forRoot(),| Filter | Skips |
|---|---|
ignoreGraphQLPlayground | GET /graphql with Accept: text/html — the Sandbox UI page load |
ignoreGraphQLIntrospection | Any POST with operationName: IntrospectionQuery or a query referencing __schema / __type |
What is captured
Each profiled GraphQL request shows a GQL badge in /_profiler and records:
| Field | Description |
|---|---|
operationType | query, mutation, or subscription |
operationName | Named operation (e.g. GetBooks), if provided |
fieldName | Entry-point resolver field |
query | The full GraphQL document (formatted) |
variables | Variables object |
Registering this module installs the graphql entrypoint type: GraphQL operations get their own GraphQL view on /_profiler, with a filter bar including an Operation filter (query / mutation / subscription).
GraphQL-level errors (schema validation failures, resolver errors) appear in the Exceptions tab with an amber GraphQLError badge, distinct from NestJS runtime exceptions. Since GraphQL names every error GraphQLError, its extensions.code is shown alongside — that code is what the Exception filter lists and what decides whether the operation counts as an error.

Options
GraphQLCollectorModule.forRoot(options) accepts:
| Option | Default | Description |
|---|---|---|
enabled | true | Enable GraphQL profiling. |
error | INTERNAL_SERVER_ERROR | What counts as a failed operation. A GraphQL response is 200 even when it failed, so statuses say nothing and extensions.code takes their role. |
A BAD_REQUEST (what the Nest Apollo driver emits for a rejected mutation), BAD_USER_INPUT, UNAUTHENTICATED or NOT_FOUND is the schema answering correctly — GraphQL's equivalent of a 4xx — so none of them is an error by default. An error carrying no code counts, as an unmapped throw is a genuine failure.
// Here, a failed login is an incident worth surfacing.
GraphQLCollectorModule.forRoot({
error: { codes: ['INTERNAL_SERVER_ERROR', 'UNAUTHENTICATED'] },
});Use forRootAsync to resolve the options from ConfigService. See What counts as an error.
How it works
GraphQLCollectorModule registers GraphQLContextAdapter with ProfilerCoreService on module init. The adapter supports all NestJS GraphQL drivers that expose the HTTP request in the execution context:
- Apollo (Express / Fastify): looks for
gqlCtx.req - Mercurius (Fastify): looks for
gqlCtx.request
A middleware finish hook also captures GraphQL errors for requests that Apollo handles without calling any resolver (e.g. schema validation failures), ensuring those profiles still appear in /_profiler.
Custom protocol adapters
This package is the reference implementation of the IContextAdapter pattern from @eleven-labs/nest-profiler. You can use the same pattern to profile gRPC, Kafka, WebSockets, or any other NestJS execution context — see the @eleven-labs/nest-profiler documentation for a full example.