{
    "slug": "graphql_schema_design",
    "term": "GraphQL Schema Design",
    "category": "api_design",
    "difficulty": "advanced",
    "short": "Designing GraphQL schemas that are intuitive, evolvable, and performant — with clear type hierarchies, nullable conventions, and avoiding the N+1 query problem.",
    "long": "GraphQL schema design best practices: make nullable the default (required only when absence is an error), use connection types for lists (enables pagination metadata), prefix mutations with the action (createUser, updateUser, deleteUser), use input types for mutation arguments, never return raw IDs without the entity, and solve N+1 with DataLoader batching. Versioning: GraphQL schemas evolve by adding nullable fields and deprecating old ones — never removing fields without a sunset period.",
    "aliases": [
        "GraphQL",
        "schema design",
        "GraphQL schema"
    ],
    "tags": [
        "api-design",
        "graphql",
        "performance"
    ],
    "misconception": "GraphQL automatically solves N+1 queries — without DataLoader or a similar batching mechanism, GraphQL resolvers create far more N+1 queries than REST because every field is a resolver.",
    "why_it_matters": "A naively implemented GraphQL schema can issue thousands of database queries for a single client request due to N+1 in resolvers — DataLoader batching is not optional for production.",
    "common_mistakes": [
        "No DataLoader — each resolver fetches its own data; a query for 100 users with their posts fires 101 queries.",
        "Non-null fields that should be nullable — a single null value errors the entire query instead of just that field.",
        "Mutations that return Boolean instead of the mutated type — clients cannot get updated data without a separate query.",
        "Deeply nested mutations — GraphQL mutations should be flat; nesting creates complex error handling."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "graphql",
        "n_plus_one",
        "api_design",
        "db_n_plus_one"
    ],
    "prerequisites": [
        "graphql",
        "api_design",
        "api_documentation"
    ],
    "refs": [
        "https://graphql.org/learn/best-practices/"
    ],
    "bad_code": "// N+1 without DataLoader:\ntype Query { users: [User!]! }\ntype User { posts: [Post!]! }  // Each user resolver fires a separate DB query\n// 100 users → 1 (users) + 100 (posts) = 101 queries",
    "good_code": "// DataLoader batches resolver calls:\n$postLoader = new DataLoader(function(array $userIds): array {\n    $posts = Post::whereIn('user_id', $userIds)->get()->groupBy('user_id');\n    return array_map(fn($id) => $posts[$id] ?? [], $userIds);\n});\n\n// Resolver:\n'posts' => fn(User $user) => $postLoader->load($user->id),\n// 100 users → 1 (users) + 1 (posts batch) = 2 queries",
    "quick_fix": "Design your GraphQL schema around user queries not database tables — if users always fetch users with their orders, make that a single query even if it joins two tables",
    "severity": "medium",
    "effort": "high",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/graphql_schema_design",
        "html_url": "https://codeclaritylab.com/glossary/graphql_schema_design",
        "json_url": "https://codeclaritylab.com/glossary/graphql_schema_design.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[GraphQL Schema Design](https://codeclaritylab.com/glossary/graphql_schema_design) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/graphql_schema_design"
            }
        }
    }
}