graphql-architect

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GraphQL Architect Skill

GraphQL架构师技能

Purpose

用途

Provides expert GraphQL architecture expertise specializing in schema design, federation patterns, resolver optimization, and real-time subscriptions. Builds performant, type-safe GraphQL APIs with N+1 prevention, efficient caching, and scalable API gateway patterns across distributed systems.
提供专业的GraphQL架构技术支持,专注于Schema设计、联邦模式、解析器优化和实时订阅功能。构建高性能、类型安全的GraphQL API,包含N+1查询预防、高效缓存以及适用于分布式系统的可扩展API网关模式。

When to Use

适用场景

  • Designing GraphQL schema from scratch for new APIs
  • Implementing GraphQL federation across multiple services
  • Optimizing resolvers to prevent N+1 queries (DataLoader implementation)
  • Building real-time features with GraphQL subscriptions
  • Migrating from REST to GraphQL or designing hybrid REST+GraphQL APIs
  • Implementing GraphQL API gateway patterns
  • 为新API从零开始设计GraphQL Schema
  • 在多个服务中实现GraphQL联邦
  • 优化解析器以预防N+1查询(DataLoader实现)
  • 基于GraphQL订阅构建实时功能
  • 从REST迁移至GraphQL,或设计REST+GraphQL混合API
  • 实现GraphQL API网关模式

Quick Start

快速开始

Invoke this skill when:
  • Designing new GraphQL schemas or federation architecture
  • Solving N+1 query performance issues
  • Implementing real-time subscriptions
  • Migrating REST APIs to GraphQL
Do NOT invoke when:
  • Simple REST API is sufficient (use api-designer)
  • Database schema design without API layer (use database-administrator)
  • Frontend data fetching only (use frontend-developer)
在以下场景调用此技能:
  • 设计新的GraphQL Schema或联邦架构
  • 解决N+1查询的性能问题
  • 实现实时订阅功能
  • 将REST API迁移至GraphQL
请勿在以下场景调用:
  • 简单REST API即可满足需求(请使用api-designer)
  • 仅设计数据库Schema而无需API层(请使用database-administrator)
  • 仅涉及前端数据获取(请使用frontend-developer)

Core Capabilities

核心能力

Schema Design

Schema设计

  • Creating type-safe GraphQL schemas with best practices
  • Implementing pagination patterns (Relay, offset-based)
  • Designing mutations with input validation and error handling
  • Managing schema evolution and backward compatibility
  • 遵循最佳实践创建类型安全的GraphQL Schema
  • 实现分页模式(Relay、基于偏移量)
  • 设计带输入验证和错误处理的Mutations
  • 管理Schema演进与向后兼容性

Federation Architecture

联邦架构

  • Implementing Apollo Federation for microservices
  • Configuring schema stitching for service composition
  • Managing cross-service queries and mutations
  • Setting up API gateways for schema composition
  • 为微服务实现Apollo Federation
  • 配置Schema Stitching以实现服务组合
  • 管理跨服务查询与Mutations
  • 搭建用于Schema组合的API网关

Resolver Optimization

解析器优化

  • Implementing DataLoader for N+1 prevention
  • Caching strategies at resolver and field levels
  • Query complexity analysis and depth limiting
  • Persisted queries for production optimization
  • 实现DataLoader以预防N+1查询
  • 解析器和字段级别的缓存策略
  • 查询复杂度分析与深度限制
  • 生产环境下的持久化查询优化

Real-Time Subscriptions

实时订阅

  • Implementing WebSocket-based subscriptions
  • Managing subscription lifecycle and cleanup
  • Integrating with event-driven backends
  • Handling subscription authentication and authorization
  • 实现基于WebSocket的订阅功能
  • 管理订阅生命周期与资源清理
  • 与事件驱动型后端集成
  • 处理订阅的认证与授权

Decision Framework

决策框架

GraphQL vs REST Decision Matrix

GraphQL vs REST决策矩阵

FactorUse GraphQLUse REST
Client typesMultiple clients with different needsSingle client with predictable needs
Data relationshipsHighly nested, interconnected dataFlat resources with few relationships
Over-fetchingClients need different subsetsClients typically need all fields
Under-fetchingAvoid multiple round tripsSingle endpoint provides enough
Schema evolutionFrequent changes, backward compatStable API, versioning acceptable
Real-timeSubscriptions neededPolling or webhooks sufficient
考量因素选择GraphQL选择REST
客户端类型多客户端且需求各异单一客户端且需求可预测
数据关系高度嵌套、相互关联的数据扁平化资源且关联较少
过度获取客户端需要不同的数据子集客户端通常需要全部字段
获取不足避免多次请求往返单个端点即可满足需求
Schema演进频繁变更且需向后兼容API稳定,版本化可接受
实时性需要订阅功能轮询或WebHook即可满足

Schema Design Decision Tree

Schema设计决策树

Schema Design Requirements
├─ Single service (monolith)?
│  └─ Schema-first design with single schema
├─ Multiple microservices?
│  ├─ Services owned by different teams?
│  │  └─ Apollo Federation
│  └─ Services owned by same team?
│     └─ Schema stitching (simpler)
├─ Existing REST APIs to wrap?
│  └─ GraphQL wrapper layer
└─ Need backward compatibility?
   └─ Hybrid REST + GraphQL
Schema设计需求
├─ 单一服务(单体应用)?
│  └─ 采用Schema优先设计,使用单一Schema
├─ 多微服务?
│  ├─ 服务由不同团队维护?
│  │  └─ 使用Apollo Federation
│  └─ 服务由同一团队维护?
│     └─ 使用Schema Stitching(更简单)
├─ 已有REST API需要封装?
│  └─ 搭建GraphQL封装层
└─ 需要向后兼容性?
   └─ 采用REST+GraphQL混合架构

N+1 Prevention Strategy

N+1查询预防策略

Resolver Implementation
├─ Field resolves to single related entity?
│  └─ DataLoader with batching
├─ Field resolves to list of related entities?
│  ├─ List size always small (<10)?
│  │  └─ Direct query acceptable
│  └─ List size unbounded?
│     └─ DataLoader with batching + pagination
├─ Nested resolvers (users → posts → comments)?
│  └─ Multi-level DataLoaders
└─ Aggregations or counts?
   └─ Separate DataLoader for counts
解析器实现
├─ 字段关联单个实体?
│  └─ 使用DataLoader实现批量查询
├─ 字段关联实体列表?
│  ├─ 列表规模始终较小(<10条)?
│  │  └─ 直接查询即可
│  └─ 列表规模无上限?
│     └─ 结合DataLoader批量查询与分页
├─ 嵌套解析器(用户 → 帖子 → 评论)?
│  └─ 多层级DataLoader
└─ 需要聚合或计数?
   └─ 为计数单独配置DataLoader

Core Workflow: DataLoader Implementation

核心工作流:DataLoader实现

Problem: N+1 queries killing performance
typescript
// WITHOUT DataLoader - N+1 problem
const resolvers = {
  Post: {
    author: async (post, _, { db }) => {
      // Executed once per post (N+1 problem!)
      return db.User.findByPk(post.userId);
    }
  }
};
// Query for 100 posts triggers 101 DB queries
Solution: Batch with DataLoader
typescript
import DataLoader from 'dataloader';

// Create loader per request (important!)
function createLoaders(db) {
  return {
    userLoader: new DataLoader(async (userIds) => {
      const users = await db.User.findAll({
        where: { id: userIds }
      });
      // Return in same order as requested IDs
      const userMap = new Map(users.map(u => [u.id, u]));
      return userIds.map(id => userMap.get(id));
    })
  };
}

// Resolver using DataLoader
const resolvers = {
  Post: {
    author: (post, _, { loaders }) => {
      return loaders.userLoader.load(post.userId);
    }
  }
};
// Same query now triggers 2 queries total!
问题:N+1查询导致性能急剧下降
typescript
// 未使用DataLoader - 存在N+1问题
const resolvers = {
  Post: {
    author: async (post, _, { db }) => {
      // 每个帖子执行一次查询(N+1问题!)
      return db.User.findByPk(post.userId);
    }
  }
};
// 查询100条帖子会触发101次数据库查询
解决方案:使用DataLoader实现批量查询
typescript
import DataLoader from 'dataloader';

// 每个请求创建独立的Loader(很重要!)
function createLoaders(db) {
  return {
    userLoader: new DataLoader(async (userIds) => {
      const users = await db.User.findAll({
        where: { id: userIds }
      });
      // 按照请求ID的顺序返回结果
      const userMap = new Map(users.map(u => [u.id, u]));
      return userIds.map(id => userMap.get(id));
    })
  };
}

// 使用DataLoader的解析器
const resolvers = {
  Post: {
    author: (post, _, { loaders }) => {
      return loaders.userLoader.load(post.userId);
    }
  }
};
// 相同查询现在仅触发2次数据库查询!

Quick Reference: Schema Best Practices

快速参考:Schema最佳实践

Pagination Pattern (Relay-style)

分页模式(Relay风格)

graphql
type Query {
  users(first: Int, after: String, last: Int, before: String): UserConnection!
}

type UserConnection {
  edges: [UserEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

type UserEdge {
  node: User!
  cursor: String!
}

type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  startCursor: String
  endCursor: String
}
graphql
type Query {
  users(first: Int, after: String, last: Int, before: String): UserConnection!
}

type UserConnection {
  edges: [UserEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

type UserEdge {
  node: User!
  cursor: String!
}

type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  startCursor: String
  endCursor: String
}

Error Handling Pattern

错误处理模式

graphql
type Mutation {
  createUser(input: CreateUserInput!): CreateUserPayload!
}

type CreateUserPayload {
  user: User
  errors: [UserError!]!
}

type UserError {
  field: String
  message: String!
  code: ErrorCode!
}

enum ErrorCode {
  VALIDATION_ERROR
  NOT_FOUND
  UNAUTHORIZED
  CONFLICT
}
graphql
type Mutation {
  createUser(input: CreateUserInput!): CreateUserPayload!
}

type CreateUserPayload {
  user: User
  errors: [UserError!]!
}

type UserError {
  field: String
  message: String!
  code: ErrorCode!
}

enum ErrorCode {
  VALIDATION_ERROR
  NOT_FOUND
  UNAUTHORIZED
  CONFLICT
}

Red Flags - When to Escalate

预警信号 - 需升级处理的场景

ObservationWhy Escalate
Query complexity explosionUnbounded nested queries causing DoS
Federation circular dependenciesSchema design issue
10K+ concurrent subscriptionsInfrastructure architecture
Schema versioning across 50+ fieldsBreaking change management
Cross-service transaction needsDistributed systems pattern
现象升级原因
查询复杂度急剧上升无限制的嵌套查询可能导致拒绝服务(DoS)
联邦架构出现循环依赖Schema设计存在问题
并发订阅数超过10000涉及基础设施架构调整
Schema版本变更涉及50+字段需处理破坏性变更管理
跨服务事务需求涉及分布式系统模式设计

Additional Resources

额外资源

  • Detailed Technical Reference: See REFERENCE.md
    • Apollo Federation setup workflow
    • Field-level authorization directives
    • Query complexity limiting
  • Code Examples & Patterns: See EXAMPLES.md
    • Anti-patterns (N+1 queries, no complexity limits)
    • Integration patterns with other skills
    • Complete resolver implementations
  • 详细技术参考:查看REFERENCE.md
    • Apollo Federation搭建流程
    • 字段级授权指令
    • 查询复杂度限制
  • 代码示例与模式:查看EXAMPLES.md
    • 反模式(N+1查询、无复杂度限制)
    • 与其他技能的集成模式
    • 完整的解析器实现示例