Skip to content

NestJS GraphQL Resolvers

Resolvers are the GraphQL counterpart to controllers. This lesson covers writing queries, mutations, arguments, and field-level resolvers in Nest.

Queries and Mutations

A resolver class decorated with @Resolver() hosts @Query and @Mutation methods. Arguments use @Args() similar to @Body()/@Param() in REST, and return types are declared for schema generation.

@Mutation(() => Cat)
createCat(@Args('input') input: CreateCatInput) {
  return this.catsService.create(input);
}

@Query(() => Cat)
cat(@Args('id', { type: () => ID }) id: string) {
  return this.catsService.findOne(id);
}

The return type functions (() => Cat) exist because of TypeScript emit limitations and are required in code-first mode.

Field Resolvers

@ResolveField(() => String)
displayName(@Parent() cat: Cat) {
  return `${cat.name} (${cat.breed})`;
}
  • @Parent() gives the parent object when resolving a nested field.
  • Field resolvers run per parent object—watch N+1 database queries.
  • Use DataLoader patterns for batching nested lookups.
  • Guards and pipes can decorate resolver methods like controllers.

Resolver Decorators Cheatsheet

Decorators used in Nest GraphQL resolvers.

Decorator Purpose
@Resolver() Marks a resolver class
@Query() Defines a query operation
@Mutation() Defines a mutation operation
@Args() Reads GraphQL arguments
@ResolveField() Resolves a nested field
@Parent() Accesses the parent entity

Input Types

Code-first uses @InputType() classes for mutation arguments, often mirroring DTO validation with class-validator and ValidationPipe.

Errors in Resolvers

Throw Nest HTTP exceptions or GraphQL-friendly exceptions from services; map them consistently so clients receive predictable error shapes.

Common Mistakes

  • Fetching related data inside loops without batching (N+1).
  • Returning entire database entities with sensitive fields.
  • Duplicating business logic across multiple resolvers instead of sharing a service.
  • Forgetting return type functions in code-first decorators.

Key Takeaways

  • Resolvers host GraphQL queries, mutations, and field resolvers.
  • @Args and InputTypes define operation inputs.
  • Field resolvers need care to avoid N+1 queries.
  • Keep resolvers thin; reuse services.

Pro Tip

If a field is expensive, make it explicitly opt-in in the schema description and document client cost—do not silently compute heavy fields for every list query.