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