GraphQL Subscriptions & Advanced Patterns
GraphQL Subscriptions & Advanced Patterns
This lesson covers four production-grade GraphQL capabilities: real-time data via @Subscription and PubSub, resolving nested relationships with @ResolveField, eliminating the notorious N+1 problem with DataLoader, and returning structured errors through GraphQL error handling. Together they take a basic API to enterprise quality.
Real-Time with @Subscription and PubSub
Subscriptions push data to clients over a persistent WebSocket connection. NestJS wires them via @Subscription() on a resolver method and a PubSub instance that acts as the in-process event bus. For a single-server deployment the built-in PubSub from graphql-subscriptions is sufficient; in a multi-node environment replace it with a Redis-backed pub/sub.
installSubscriptionHandlers: true (Apollo Server 2) or the subscriptions-transport-ws / graphql-ws plugin configured on the GraphQLModule. HTTP alone cannot push data to clients.
Resolving Nested Types with @ResolveField
@ResolveField() teaches NestJS how to populate a field whose value is not directly on the parent entity — for example, fetching an author object whenever a Post is returned. The method receives the parent object as its first argument (injected with @Parent()) so it can issue a targeted lookup:
The N+1 Problem and DataLoader
The N+1 problem occurs when fetching a list of N posts each triggers a separate findOne query for the author, resulting in 1 list query + N author queries. DataLoader solves this by batching all author IDs collected during a single GraphQL execution tick into one query, then distributing results back to each resolver.
- Install:
npm install dataloader - Create a loader that accepts an array of IDs and returns an array of entities in the same order.
- Scope the loader to the request (use a
REQUEST-scoped provider or a NestJSDataLoaderInterceptor) so batches are per-request, not global.
GraphQL Error Handling
GraphQL errors should be meaningful and typed. NestJS propagates NestJS exceptions (e.g. NotFoundException) to the errors array in the response, but you can also throw GraphQLError directly for richer client-facing error codes:
- Throw NestJS exceptions — automatically translated to GraphQL errors with the message preserved.
- Custom error codes — use
extensions.codeonGraphQLErrorso clients can distinguish error types programmatically. - Format errors globally — configure
formatErroronGraphQLModuleto strip stack traces in production.
formatError to return only a safe message and a machine-readable code. Log full details server-side.
Summary
@Subscription + PubSub delivers real-time events over WebSockets; swap in Redis PubSub for multi-node deployments. @ResolveField populates nested types cleanly. DataLoader (REQUEST-scoped) batches nested queries and eliminates the N+1 problem. Structured error handling with formatError protects clients from leaking internals while providing actionable codes. These four patterns are the foundation of production-ready NestJS GraphQL APIs.