GraphQL API Implementation
Designing and implementing GraphQL APIs — from schema design and resolvers through subscriptions, federation, caching, and security.
When to Use
- Building flexible APIs where clients control response shape
- Reducing over-fetching and under-fetching (vs REST)
- Implementing real-time subscriptions
- Aggregating data from multiple sources (federation)
- Mobile apps needing efficient data loading
Schema Design
SCHEMA_TEMPLATE = """
type Query {
user(id: ID!): User
users(page: Int, limit: Int): UserConnection!
search(query: String!): [SearchResult!]!
}
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, input: UpdateUserInput!): User!
deleteUser(id: ID!): Boolean!
}
type Subscription {
userCreated: User!
userUpdated(id: ID!): User!
}
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
createdAt: DateTime!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
input CreateUserInput {
name: String!
email: String!
}
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
}
"""
Common Pitfalls
- N+1 problem — loading related objects causes many DB queries; use DataLoader
- Overly deep queries — malicious queries can cause performance issues; set depth limits
- No caching — POST requests don't cache naturally; use automatic persisted queries, CDN
- Schema debt — fields that should be deprecated linger forever; use deprecation reason
- Auth in resolvers — authorization must be uniform, not scattered across resolvers
Verification Checklist
- Schema follows conventions (types, inputs, enums, pagination)
- DataLoader implemented for batching
- Query complexity/depth limiting configured
- Authentication middleware at transport level
- Authorization in business logic layer (not resolvers)
- Subscriptions secured (auth on connect)
- Federation-ready (if multiple services)