Designing GraphQL Architecture
1. Designing GraphQL Schema Architecture
| Element | Description |
|---|---|
| Type | Object, Interface, Union, Enum, Scalar |
| Query | Read entry points |
| Mutation | Write entry points |
| Subscription | Real-time over WS/SSE |
| Directive | @deprecated, @auth, custom |
| Naming | PascalCase types; camelCase fields |
2. Designing Query Optimization
| Technique | Detail |
|---|---|
| DataLoader | Batch + cache per request |
| Persisted queries | Hash → query; smaller payloads, allowlist |
| Field projection | Push selection set into SQL |
| Defer/Stream | Send fast fields first |
| Caching | Per-resolver, per-field TTL |
3. Designing DataLoader Pattern
Example: DataLoader (Node.js)
import DataLoader from "dataloader";
const userLoader = new DataLoader(async (ids) => {
const rows = await db.query("SELECT * FROM users WHERE id = ANY($1)", [ids]);
const byId = new Map(rows.map(r => [r.id, r]));
return ids.map(id => byId.get(id) ?? null);
});
// In resolver:
const author = await userLoader.load(post.authorId);
| Property | Detail |
|---|---|
| Scope | Per-request (avoid cross-request leaks) |
| Batches | Within event loop tick |
| Caches | By key for life of request |
4. Designing Mutations and Subscriptions
| Pattern | Detail |
|---|---|
| Input type | Single input arg per mutation |
| Payload type | Return modified entity + clientMutationId |
| Errors as data | Union: SuccessResult | ValidationError |
| Subscriptions | graphql-ws over WebSocket |
5. Designing Authentication and Authorization
| Layer | Approach |
|---|---|
| AuthN | JWT in HTTP header → context |
| AuthZ | Per-field directive @auth(role: ADMIN) |
| Resolver guard | Check entitlement against ctx.user |
| Field masking | Return null for unauthorized fields |
6. Designing Schema Federation
| Concept | Detail |
|---|---|
| Subgraph | Owns slice of schema (e.g., Reviews) |
| Supergraph | Composed schema served by router |
| Entity | Type extended across subgraphs (@key) |
| Reference resolver | Fetch entity by key |
| Tools | Apollo Federation v2, GraphQL Mesh |
7. Designing Query Complexity Analysis
| Strategy | Detail |
|---|---|
| Depth limit | Reject queries deeper than N |
| Cost analysis | Sum field costs; reject if > budget |
| Pagination caps | Max first/last per connection |
| Persisted queries only | Safest; allow only known queries |
8. Designing Caching Strategy
| Layer | Detail |
|---|---|
| CDN (persisted GETs) | Cacheable URLs from query hash |
| Per-resolver | Cache by args + parent id |
| Object cache | Apollo Server Response Cache |
| Client | Apollo Client / Relay normalized cache |
9. Designing Error Handling
| Pattern | Detail |
|---|---|
| errors[] in response | Standard partial-error mode |
| extensions.code | Machine-readable code (UNAUTHENTICATED) |
| Errors as union types | Type-safe expected errors |
| Avoid leaking internals | Mask stack traces in prod |
10. Designing Pagination and Filtering
| Spec | Detail |
|---|---|
| Relay Cursor Connections | edges, node, pageInfo, cursors |
| first / after / last / before | Forward + backward cursors |
| Filter input | where: { status: ACTIVE, createdAfter: ... } |
| Sort | orderBy: [{field: CREATED_AT, dir: DESC}] |
11. Designing Rate Limiting for GraphQL
| Approach | Detail |
|---|---|
| Per request count | Insufficient — 1 query may be huge |
| Cost-based | Charge each field; cap budget per minute |
| Persisted query allowlist | Pre-known costs |
| Per-operation | Limit by operation name |
12. Designing Schema Stitching
| vs Federation | Detail |
|---|---|
| Stitching | Gateway introspects + merges remote schemas |
| Federation | Subgraphs declare ownership via directives |
| When to use stitching | Aggregating 3rd-party GraphQL APIs |
| Tools | GraphQL Tools, Mesh |