home / skills / secondsky / claude-skills / graphql-implementation

This skill helps you design and implement scalable GraphQL APIs with schema, resolvers, error handling, and performance optimizations.

npx playbooks add skill secondsky/claude-skills --skill graphql-implementation

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
2.8 KB
---
name: graphql-implementation
description: Builds GraphQL APIs with schema design, resolvers, error handling, and performance optimization using Apollo or Graphene. Use when creating flexible query APIs, migrating from REST, or implementing real-time subscriptions.
---

# GraphQL Implementation

Build GraphQL APIs with proper schema design, resolvers, and performance optimization.

## Schema Definition

```graphql
type User {
  id: ID!
  name: String!
  email: String!
  posts(limit: Int = 10): [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
  createdAt: DateTime!
}

type Query {
  user(id: ID!): User
  users(limit: Int, offset: Int): [User!]!
  post(id: ID!): Post
}

type Mutation {
  createUser(input: CreateUserInput!): User!
  createPost(input: CreatePostInput!): Post!
}

input CreateUserInput {
  name: String!
  email: String!
}
```

## Apollo Server Setup

```javascript
const { ApolloServer } = require('@apollo/server');
const { startStandaloneServer } = require('@apollo/server/standalone');

const resolvers = {
  Query: {
    user: (_, { id }, { dataSources }) =>
      dataSources.userAPI.getUser(id),
    users: (_, { limit, offset }, { dataSources }) =>
      dataSources.userAPI.getUsers({ limit, offset })
  },
  User: {
    posts: (user, { limit }, { dataSources }) =>
      dataSources.postAPI.getPostsByUser(user.id, limit)
  },
  Mutation: {
    createUser: (_, { input }, { dataSources }) =>
      dataSources.userAPI.createUser(input)
  }
};

const server = new ApolloServer({ typeDefs, resolvers });
```

## DataLoader for N+1 Prevention

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

const userLoader = new DataLoader(async (ids) => {
  const users = await User.find({ _id: { $in: ids } });
  return ids.map(id => users.find(u => u.id === id));
});
```

## Error Handling

```javascript
const { GraphQLError } = require('graphql');

throw new GraphQLError('User not found', {
  extensions: { code: 'NOT_FOUND', argumentName: 'id' }
});
```

## Best Practices

- Use DataLoader to batch queries
- Implement query complexity limits
- Design schema around client needs
- Validate all inputs
- Use descriptive naming conventions

## Python Graphene

See [references/python-graphene.md](references/python-graphene.md) for complete Flask implementation with:
- ObjectType definitions
- Query and Mutation classes
- Input types
- Flask integration

## Best Practices

**Do:**
- Use DataLoader to batch queries
- Implement query complexity limits
- Design schema around client needs
- Validate all inputs
- Use descriptive naming conventions
- Add subscriptions for real-time data

**Don't:**
- Allow deeply nested queries without limits
- Expose database internals
- Ignore N+1 query problems
- Return unauthorized data
- Skip input validation

Overview

This skill builds production-ready GraphQL APIs with clear schema design, resolvers, error handling, and performance optimizations using Apollo (TypeScript) or Graphene (Python). It provides patterns for DataLoader batching, query complexity controls, input validation, and optional real-time subscriptions. The goal is to accelerate migration from REST and deliver flexible client-driven query endpoints.

How this skill works

Define types, queries, mutations, and inputs as a schema-first contract that maps to resolvers and data sources. Implement resolvers that call data APIs or ORMs, and attach DataLoader instances in the request context to prevent N+1 queries. Add centralized error handling via GraphQLError extensions, and enforce limits and validation at the execution layer for safety and performance.

When to use it

  • Building a new flexible API for complex client queries and relationships
  • Migrating REST endpoints to a single GraphQL endpoint to reduce over/under fetching
  • Implementing real-time features with subscriptions
  • Optimizing performance by eliminating N+1 queries with DataLoader
  • Enforcing typed contracts and consistent error handling across services

Best practices

  • Design the schema around client needs, not database tables
  • Use DataLoader per-request to batch and cache database calls
  • Validate inputs and enforce query complexity/depth limits
  • Return descriptive GraphQLError extensions (codes, field info)
  • Avoid exposing database internals; map domain models to DTOs

Example use cases

  • User and post API with paginated fields and batched author lookups
  • Replacing multiple REST endpoints with a single GraphQL gateway
  • Adding subscriptions for live comment or notification streams
  • Protecting APIs with query depth and cost analysis in public apps
  • Implementing mutation patterns with input types and transactional resolvers

FAQ

How do I prevent N+1 database queries?

Attach DataLoader instances to the request context and batch related key lookups in resolver functions to consolidate queries.

When should I use Apollo vs Graphene?

Use Apollo with TypeScript/Node.js for JavaScript stacks and rich ecosystem tools; choose Graphene for Python applications that need tight Flask or Django integration.