Claude
Skills
Sign in
Back

api-design-patterns

Included with Lifetime
$97 forever

Comprehensive API design patterns covering REST, GraphQL, gRPC, versioning, authentication, and modern API best practices

Designapirestgraphqlgrpcarchitecturewebdesign-patterns

What this skill does

# API Design Patterns

Design robust, scalable APIs using proven patterns for REST, GraphQL, and gRPC with proper versioning, authentication, and error handling.

## Quick Reference

**API Style Selection**:
- REST: Resource-based CRUD, simple clients, HTTP-native caching
- GraphQL: Client-driven queries, complex data graphs, real-time subscriptions
- gRPC: High-performance RPC, microservices, strong typing, streaming

**Critical Patterns**:
- Versioning: URI (`/v1/users`), header (`Accept: application/vnd.api+json;version=1`), content negotiation
- Pagination: Offset (simple), cursor (stable), keyset (performant)
- Auth: OAuth2 (delegated), JWT (stateless), API keys (service-to-service)
- Rate limiting: Token bucket, fixed window, sliding window
- Idempotency: Idempotency keys, conditional requests, safe retry

**See references/ for deep dives**: `rest-patterns.md`, `graphql-patterns.md`, `grpc-patterns.md`, `versioning-strategies.md`, `authentication.md`

## Core Principles

### Universal API Design Standards

Apply these principles across all API styles:

**1. Consistency Over Cleverness**
- Follow established conventions for your API style
- Use predictable naming patterns (snake_case or camelCase, pick one)
- Maintain consistent error response formats
- Version breaking changes, never surprise clients

**2. Design for Evolution**
- Plan for versioning from day one
- Use optional fields with sensible defaults
- Deprecate gracefully with sunset dates
- Document breaking vs non-breaking changes

**3. Security by Default**
- Require authentication unless explicitly public
- Use HTTPS/TLS for all production endpoints
- Implement rate limiting and throttling
- Validate and sanitize all inputs
- Return minimal error details to clients

**4. Developer Experience First**
- Provide comprehensive documentation (OpenAPI, GraphQL schema)
- Return meaningful error messages with actionable guidance
- Use standard HTTP status codes correctly
- Include request IDs for debugging
- Offer SDKs and code generators

## API Style Decision Tree

### When to Choose REST

✅ **Use REST when:**
- Building CRUD-focused resource APIs
- Clients need HTTP caching (ETags, Cache-Control)
- Wide platform compatibility required (browsers, mobile, IoT)
- Simple, stateless client-server model fits
- Team familiar with HTTP/REST conventions

❌ **Avoid REST when:**
- Complex data fetching with nested relationships (N+1 queries)
- Real-time updates are primary use case
- Need strong typing and code generation
- High-performance RPC between microservices

**Example Use Cases**: Public APIs, mobile backends, traditional web services

### When to Choose GraphQL

✅ **Use GraphQL when:**
- Clients need flexible, client-driven queries
- Complex data graphs with nested relationships
- Multiple client types with different data needs
- Real-time subscriptions required
- Strong typing and schema validation needed

❌ **Avoid GraphQL when:**
- Simple CRUD operations dominate
- HTTP caching is critical (GraphQL uses POST)
- File uploads are primary feature (requires extensions)
- Team lacks GraphQL expertise
- Performance optimization is complex (N+1 problem)

**Example Use Cases**: Client-facing APIs, dashboards, mobile apps with varied UIs

### When to Choose gRPC

✅ **Use gRPC when:**
- Microservice-to-microservice communication
- High performance and low latency critical
- Bidirectional streaming needed
- Strong typing with Protocol Buffers
- Polyglot environments (language interop)

❌ **Avoid gRPC when:**
- Browser clients (limited support, needs grpc-web)
- HTTP/JSON required for compatibility
- Human-readable payloads preferred
- Simple request/response patterns

**Example Use Cases**: Internal microservices, streaming data, service mesh

## REST API Patterns

### Resource Naming

✅ **Good: Plural nouns, hierarchical**
```
GET    /users              # List users
GET    /users/123          # Get user
POST   /users              # Create user
PUT    /users/123          # Update user (full)
PATCH  /users/123          # Update user (partial)
DELETE /users/123          # Delete user
GET    /users/123/orders   # User's orders (sub-resource)
```

❌ **Bad: Verbs, mixed conventions**
```
GET    /getUsers           # Don't use verbs
POST   /user/create        # Don't use verbs
GET    /Users/123          # Don't capitalize
GET    /user/123           # Don't mix singular/plural
```

### HTTP Status Codes

**Success Codes**:
- `200 OK`: Successful GET, PUT, PATCH, DELETE with body
- `201 Created`: Successful POST, return Location header
- `202 Accepted`: Async operation started
- `204 No Content`: Successful DELETE, no body

**Client Error Codes**:
- `400 Bad Request`: Invalid input, validation error
- `401 Unauthorized`: Missing or invalid authentication
- `403 Forbidden`: Authenticated but insufficient permissions
- `404 Not Found`: Resource doesn't exist
- `409 Conflict`: State conflict (duplicate, version mismatch)
- `422 Unprocessable Entity`: Semantic validation error
- `429 Too Many Requests`: Rate limit exceeded

**Server Error Codes**:
- `500 Internal Server Error`: Unexpected error
- `502 Bad Gateway`: Upstream service error
- `503 Service Unavailable`: Temporary outage
- `504 Gateway Timeout`: Upstream timeout

### Error Response Format

✅ **Consistent error structure**
```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request parameters",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format",
        "code": "INVALID_FORMAT"
      }
    ],
    "request_id": "req_abc123",
    "documentation_url": "https://api.example.com/docs/errors/validation"
  }
}
```

### Pagination Patterns

**Offset Pagination** (simple, familiar):
```
GET /users?limit=20&offset=40
```
✅ Use for: Small datasets, admin interfaces
❌ Avoid for: Large datasets (skips become expensive), real-time data

**Cursor Pagination** (stable, efficient):
```
GET /users?limit=20&cursor=eyJpZCI6MTIzfQ
Response: { "data": [...], "next_cursor": "eyJpZCI6MTQzfQ" }
```
✅ Use for: Infinite scroll, real-time feeds, large datasets
❌ Avoid for: Random access, page numbers

**Keyset Pagination** (performant):
```
GET /users?limit=20&after_id=123
```
✅ Use for: Ordered data, database index friendly
❌ Avoid for: Complex sorting, multiple sort keys

See `references/rest-patterns.md` for filtering, sorting, field selection, HATEOAS

## GraphQL Patterns

### Schema Design

✅ **Good: Clear types, nullable by default**
```graphql
type User {
  id: ID!                    # Non-null ID
  email: String!             # Required field
  name: String               # Optional (nullable by default)
  createdAt: DateTime!
  orders: [Order!]!          # Non-null array of non-null orders
}

type Query {
  user(id: ID!): User
  users(first: Int, after: String): UserConnection!
}

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

input CreateUserInput {
  email: String!
  name: String
}

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

### Resolver Patterns

**Avoid N+1 Queries with DataLoader**:
```typescript
import DataLoader from 'dataloader';

const userLoader = new DataLoader(async (userIds: string[]) => {
  const users = await db.users.findMany({ where: { id: { in: userIds } } });
  return userIds.map(id => users.find(u => u.id === id));
});

// Resolver batches queries automatically
const resolvers = {
  Order: {
    user: (order) => userLoader.load(order.userId)
  }
};
```

### Query Complexity Analysis

Prevent expensive queries:
```typescript
import { createComplexityLimitRule } from 'graphql-validation-complexity';

const server = new ApolloServer({
  schema,
  validationRules: [
    createComplexityLimitRule(1000, {
      onCost: (cost) => console.log('Query cost:', cost),
    }),
  ],
});
```

See `references/graphql-patterns.md` for subscriptions, relay cursor connections, error handling

## gRPC Patterns

### Service D

Related in Design