Skip to main content
Emily Chen·

Schema, resolvers and DataLoader batching that killed our N+1 - subscriptions included

Creates a complete GraphQL API with schema design, resolvers, DataLoader optimization, and subscription support.

GraphQL API Schema & Resolver Generator

You are a GraphQL architect building a complete, production-ready API. Design and implement the schema and resolvers. ## Domain Model ``` {{domain_description}} ``` ## Technical Spec - Language: {{programming_language}} - GraphQL framework: {{graphql_framework}} (Apollo, Strawberry, gqlgen, Absinthe) - Database: {{database}} - Auth: {{auth_strategy}} ## Deliverables 1. **Schema Design** - Complete GraphQL SDL with: - Types (objects, inputs, enums, interfaces, unions) - Queries with filtering, pagination, sorting - Mutations with input validation - Subscriptions for real-time updates - Custom scalars (DateTime, JSON, Email, UUID) - Introspection-friendly descriptions 2. **Resolvers** - Complete resolver implementation: - Query resolvers with DataLoader batching - Mutation resolvers with transactions - Subscription resolvers with pub/sub - Field-level resolvers for computed properties 3. **DataLoader Setup** - Batching and deduplication for N+1 prevention 4. **Directive Implementation** - @auth, @rateLimit, @cacheControl, @deprecated 5. **Error Handling** - GraphQL-specific error formatting and extensions 6. **Auth Middleware** - Context building with user authentication 7. **Pagination** - Relay-style cursor pagination implementation 8. **Complexity Analysis** - Query cost analysis and depth limiting 9. **Schema Stitching/Federation** - If microservices context applies 10. **Tests** - Resolver tests with mocked data sources Follow GraphQL best practices. Use code-first or schema-first based on {{graphql_framework}} conventions.

Ergebnisse

GraphQL API for a blog domain (authors, posts, comments) in TypeScript with Apollo Server over Postgres. DataLoader kills the N+1. ```graphql scalar DateTime type Post { id: ID! title: String! author: Author! # resolved via DataLoader, not per-row query comments(first: Int = 10, after: String): CommentConnection! createdAt: DateTime! } type Query { posts(filter: PostFilter, first: Int = 20, after: String): PostConnection! } type Mutation { publishPost(input: PublishPostInput!): Post! @auth(role: AUTHOR) } type Subscription { commentAdded(postId: ID!): Comment! } ``` ```typescript // Batched author lookup — one query for N posts const authorLoader = new DataLoader<string, Author>(async (ids) => { const rows = await db.author.findMany({ where: { id: { in: [...ids] } } }); const byId = new Map(rows.map((r) => [r.id, r])); return ids.map((id) => byId.get(id)!); }); const resolvers = { Post: { author: (p, _a, ctx) => ctx.loaders.author.load(p.authorId) }, Mutation: { publishPost: (_p, { input }, ctx) => ctx.db.$transaction((tx) => tx.post.update({ where: { id: input.id }, data: { published: true } })), }, }; ``` **Included:** Relay-style cursor pagination, an `@auth` directive checking the JWT in context, pub/sub-backed `commentAdded` subscription, and depth-limiting (max 7) to block abusive nested queries. Resolver tests mock the data sources.

Modell: Claude Sonnet 4

23 Likes6 SavesScore: 11

1 Kommentar

Luca Brunner·

I was skeptical but the output is genuinely production-grade.