Schema design principles in GraphQL

From the GraphQL cheat sheet · Best Practices · verified Jul 2026

Schema design principles

graphql
# GOOD Schema Design
type User {
  id: ID!
  name: String!
  email: String!
  profile: UserProfile!
  posts(
    limit: Int = 10
    offset: Int = 0
    orderBy: PostOrderBy = CREATED_AT_DESC
  ): PostConnection!
}

# Use connections for pagination
type PostConnection {
  edges: [PostEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

type PostEdge {
  node: Post!
  cursor: String!
}

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

# Use input types for complex arguments
input CreatePostInput {
  title: String!
  content: String!
  tags: [String!]
  published: Boolean = false
}

# Use enums for fixed values
enum PostOrderBy {
  CREATED_AT_ASC
  CREATED_AT_DESC
  TITLE_ASC
  TITLE_DESC
  POPULARITY
}

# Deprecate instead of removing
type Post {
  id: ID!
  title: String!
  content: String!
  body: String! @deprecated(reason: "Use 'content' instead")
  author: User!
  tags: [String!]!
}

# BAD Schema Design (Avoid these)
type User {
  userId: String! # Use 'id: ID!' instead
  user_name: String! # Use camelCase: userName
  getPosts: [Post] # Don't use verbs, just 'posts'
  postsArray: [Post] # Redundant 'Array' suffix
}

# Too nested (BAD)
type User {
  posts: [Post!]!
    comments: [Comment!]!
      replies: [Reply!]!
        reactions: [Reaction!]! # Too deep!
}
💡 Design schema for clients, not database
⚡ Use clear, consistent naming
📌 Avoid deep nesting (max 3-4 levels)
🎯 Version via field deprecation, not versions

More GraphQL tasks

Back to the full GraphQL cheat sheet