Back to Skills

graphql-resolvers

verified

Write efficient resolvers with DataLoader, batching, and N+1 prevention

View on GitHub

Marketplace

pluginagentmarketplace-graphql

pluginagentmarketplace/custom-plugin-graphql

Plugin

developer-roadmap

Repository

pluginagentmarketplace/custom-plugin-graphql
1stars

skills/graphql-resolvers/SKILL.md

Last Verified

January 20, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/pluginagentmarketplace/custom-plugin-graphql/blob/main/skills/graphql-resolvers/SKILL.md -a claude-code --skill graphql-resolvers

Installation paths:

Claude
.claude/skills/graphql-resolvers/
Powered by add-skill CLI

Instructions

# GraphQL Resolvers Skill

> Build performant data fetching with proper patterns

## Overview

Master resolver implementation including the critical DataLoader pattern for preventing N+1 queries, context design, and error handling strategies.

---

## Quick Reference

| Pattern | Purpose | When to Use |
|---------|---------|-------------|
| DataLoader | Batch + cache | Any relationship field |
| Context | Request-scoped data | Auth, loaders, datasources |
| Field resolver | Computed fields | Derived data |
| Root resolver | Entry points | Query/Mutation fields |

---

## Core Patterns

### 1. Resolver Signature

```javascript
// (parent, args, context, info) => result

const resolvers = {
  Query: {
    // Root resolver - parent is undefined
    user: async (_, { id }, { dataSources }) => {
      return dataSources.users.findById(id);
    },
  },

  User: {
    // Field resolver - parent is User object
    posts: async (user, { first = 10 }, { loaders }) => {
      return loaders.postsByAuthor.load(user.id);
    },

    // Computed field - sync is fine
    fullName: (user) => `${user.firstName} ${user.lastName}`,

    // Default resolver (implicit)
    // email: (user) => user.email,
  },
};
```

### 2. DataLoader Pattern

```javascript
const DataLoader = require('dataloader');

// N+1 Problem:
// Query: { users { posts { title } } }
// Without DataLoader: 1 + N queries

// Solution: Batch loading
const createLoaders = () => ({
  // Batch by foreign key
  postsByAuthor: new DataLoader(async (authorIds) => {
    // 1. Single query for all authors
    const posts = await db.posts.findAll({
      where: { authorId: { [Op.in]: authorIds } }
    });

    // 2. Group by author
    const postsByAuthor = {};
    posts.forEach(post => {
      if (!postsByAuthor[post.authorId]) {
        postsByAuthor[post.authorId] = [];
      }
      postsByAuthor[post.authorId].push(post);
    });

    // 3. Return in same order as input
    return authorIds.map(id => postsByAuthor[id] || 

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
6107 chars