graphql-rs

GraphQL Fundamentals: Visual Guide

🎯 What is GraphQL?

GraphQL is a query language for APIs and a runtime for executing queries by using a type system you define for your data. Unlike REST APIs that expose multiple endpoints for different resources, GraphQL provides a single endpoint that can return exactly the data you request.

πŸ”„ REST vs GraphQL: Visual Comparison

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           REST API                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  GET /users/1        β†’ { id: 1, name: "John", email: "..." }   β”‚
β”‚  GET /users/1/posts  β†’ [ { id: 1, title: "...", body: "..." }] β”‚
β”‚  GET /posts/1        β†’ { id: 1, title: "...", author_id: 1 }   β”‚
β”‚                                                                 β”‚
β”‚  πŸ”΄ Problems:                                                   β”‚
β”‚  β€’ Multiple round trips                                         β”‚
β”‚  β€’ Over-fetching (getting unused fields)                       β”‚
β”‚  β€’ Under-fetching (need another request)                       β”‚
β”‚  β€’ API versioning challenges                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          GraphQL                               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  POST /graphql                                                  β”‚
β”‚  {                                                              β”‚
β”‚    user(id: 1) {                                                β”‚
β”‚      name                                                       β”‚
β”‚      posts { title }                                            β”‚
β”‚    }                                                            β”‚
β”‚  }                                                              β”‚
β”‚                                                                 β”‚
β”‚  βœ… Benefits:                                                   β”‚
β”‚  β€’ Single request                                               β”‚
β”‚  β€’ Get exactly what you need                                    β”‚
β”‚  β€’ Strongly typed                                               β”‚
β”‚  β€’ Self-documenting                                             β”‚
β”‚  β€’ No versioning needed                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ—οΈ GraphQL Request Lifecycle: Complete Visual Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Client    β”‚    β”‚    HTTP     β”‚    β”‚  GraphQL    β”‚    β”‚   Schema    β”‚
β”‚ Application β”‚    β”‚   Server    β”‚    β”‚   Runtime   β”‚    β”‚  + Types    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                   β”‚                   β”‚                   β”‚
        β”‚ 1. GraphQL Query  β”‚                   β”‚                   β”‚
        β”‚ ──────────────────▢                   β”‚                   β”‚
        β”‚                   β”‚ 2. Parse Query    β”‚                   β”‚
        β”‚                   β”‚ ──────────────────▢                   β”‚
        β”‚                   β”‚                   β”‚ 3. Validate       β”‚
        β”‚                   β”‚                   β”‚ ──────────────────▢
        β”‚                   β”‚                   β”‚                   β”‚
        β”‚                   β”‚                   β”‚ 4. Execute        β”‚
        β”‚                   β”‚ ◀─────────────────── (Field Resolution)
        β”‚                   β”‚                   β”‚                   β”‚
        β”‚ 5. JSON Response  β”‚                   β”‚                   β”‚
        β”‚ ◀──────────────────                   β”‚                   β”‚

Step-by-Step Breakdown

1. Client sends GraphQL Query

query GetUserProfile {
  user(id: "123") {
    name
    email
    posts {
      title
      publishedAt
    }
  }
}

2. Parse Query into AST (Abstract Syntax Tree)

Document
β”œβ”€β”€ Operation (Query)
    β”œβ”€β”€ Field: user
    β”‚   β”œβ”€β”€ Argument: id = "123"
    β”‚   └── SelectionSet
    β”‚       β”œβ”€β”€ Field: name
    β”‚       β”œβ”€β”€ Field: email
    β”‚       └── Field: posts
    β”‚           └── SelectionSet
    β”‚               β”œβ”€β”€ Field: title
    β”‚               └── Field: publishedAt

3. Validate Against Schema

βœ… Field 'user' exists on Query type
βœ… Argument 'id' is valid for user field
βœ… Fields 'name', 'email' exist on User type
βœ… Field 'posts' returns [Post] type
βœ… Fields 'title', 'publishedAt' exist on Post type

4. Execute & Resolve Fields

Execution Tree:
β”œβ”€β”€ user(id: "123")           β†’ Call user resolver
    β”œβ”€β”€ name                  β†’ Return user.name
    β”œβ”€β”€ email                 β†’ Return user.email
    └── posts                 β†’ Call posts resolver
        β”œβ”€β”€ [0].title         β†’ Return post1.title
        β”œβ”€β”€ [0].publishedAt   β†’ Return post1.publishedAt
        β”œβ”€β”€ [1].title         β†’ Return post2.title
        └── [1].publishedAt   β†’ Return post2.publishedAt

5. Return JSON Response

{
  "data": {
    "user": {
      "name": "John Doe",
      "email": "john@example.com",
      "posts": [
        {
          "title": "GraphQL is Amazing",
          "publishedAt": "2024-01-15"
        },
        {
          "title": "Building APIs with Rust",
          "publishedAt": "2024-01-20"
        }
      ]
    }
  }
}

πŸ“‹ Core GraphQL Concepts: Visual Guide

1. Schema Definition Language (SDL)

The schema is the contract between client and server:

# Object Type - describes data structure
type User {
  id: ID!           # Non-null ID scalar
  name: String!     # Non-null String scalar  
  email: String     # Nullable String scalar
  age: Int          # Nullable Integer scalar
  posts: [Post!]!   # Non-null list of non-null Posts
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!     # Connection back to User
  tags: [String!]   # List of non-null strings
}

# Root Query Type - entry points
type Query {
  user(id: ID!): User           # Get user by ID
  users: [User!]!               # Get all users
  post(id: ID!): Post           # Get post by ID
  searchPosts(query: String!): [Post!]!  # Search posts
}

2. Type System Hierarchy

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        GraphQL Types                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                 β”‚
β”‚  Scalar Types (Leaf nodes)                                      β”‚
β”‚  β”œβ”€β”€ Built-in: String, Int, Float, Boolean, ID                 β”‚
β”‚  └── Custom: DateTime, Email, URL, JSON                        β”‚
β”‚                                                                 β”‚
β”‚  Object Types (Complex structures)                             β”‚
β”‚  β”œβ”€β”€ Fields with other types                                   β”‚
β”‚  β”œβ”€β”€ Can implement interfaces                                  β”‚
β”‚  └── Can be part of unions                                     β”‚
β”‚                                                                 β”‚
β”‚  Interface Types (Abstract contracts)                          β”‚
β”‚  β”œβ”€β”€ Define common fields                                      β”‚
β”‚  └── Implemented by objects                                    β”‚
β”‚                                                                 β”‚
β”‚  Union Types (One of many types)                               β”‚
β”‚  β”œβ”€β”€ SearchResult = User | Post | Comment                      β”‚
β”‚  └── Used for heterogeneous collections                       β”‚
β”‚                                                                 β”‚
β”‚  Enum Types (Limited values)                                   β”‚
β”‚  β”œβ”€β”€ Status = DRAFT | PUBLISHED | ARCHIVED                     β”‚
β”‚  └── Provides type safety                                      β”‚
β”‚                                                                 β”‚
β”‚  Input Types (For arguments)                                   β”‚
β”‚  β”œβ”€β”€ CreateUserInput { name: String!, email: String! }        β”‚
β”‚  └── Used in mutations and query arguments                     β”‚
β”‚                                                                 β”‚
β”‚  Type Modifiers                                                β”‚
β”‚  β”œβ”€β”€ Non-Null: String! (required)                             β”‚
β”‚  β”œβ”€β”€ List: [String] (array of strings)                        β”‚
β”‚  └── Non-Null List: [String!]! (required array of required)   β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3. Field Resolution: How Data Flows

Query: { user(id: "123") { name, posts { title } } }

Resolution Process:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Step 1: Resolve Root Field                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ user(id: "123")                                             β”‚ β”‚
β”‚  β”‚ β”œβ”€β”€ Call: UserResolver.user(id: "123")                     β”‚ β”‚
β”‚  β”‚ β”œβ”€β”€ Returns: User { id: "123", name: "John", ... }         β”‚ β”‚
β”‚  β”‚ └── Type: User                                              β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                β”‚                                β”‚
β”‚  Step 2: Resolve Object Fields                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ user.name                                                   β”‚ β”‚
β”‚  β”‚ β”œβ”€β”€ Direct property access                                  β”‚ β”‚
β”‚  β”‚ β”œβ”€β”€ Returns: "John"                                         β”‚ β”‚
β”‚  β”‚ └── Type: String!                                           β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                β”‚                                β”‚
β”‚  Step 3: Resolve Nested Objects                                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ user.posts                                                  β”‚ β”‚
β”‚  β”‚ β”œβ”€β”€ Call: PostResolver.posts(user: User)                   β”‚ β”‚
β”‚  β”‚ β”œβ”€β”€ Returns: [Post{title: "..."}, Post{title: "..."}]      β”‚ β”‚
β”‚  β”‚ └── Type: [Post!]!                                          β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                β”‚                                β”‚
β”‚  Step 4: Resolve List Items                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ posts[0].title, posts[1].title                              β”‚ β”‚
β”‚  β”‚ β”œβ”€β”€ Direct property access for each post                    β”‚ β”‚
β”‚  β”‚ β”œβ”€β”€ Returns: ["Post 1 Title", "Post 2 Title"]              β”‚ β”‚
β”‚  β”‚ └── Type: String! (for each)                                β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Final Result:
{
  "data": {
    "user": {
      "name": "John",
      "posts": [
        { "title": "Post 1 Title" },
        { "title": "Post 2 Title" }
      ]
    }
  }
}

πŸš€ GraphQL Operations: Visual Guide

Queries vs Mutations vs Subscriptions

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                            QUERIES                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Purpose: Read data (like HTTP GET)                            β”‚
β”‚  Side Effects: None (idempotent)                                β”‚
β”‚  Execution: Can run in parallel                                 β”‚
β”‚  Caching: Safe to cache results                                β”‚
β”‚                                                                 β”‚
β”‚  query GetUser($id: ID!) {                                     β”‚
β”‚    user(id: $id) {                                              β”‚
β”‚      name                                                       β”‚
β”‚      email                                                      β”‚
β”‚    }                                                            β”‚
β”‚  }                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           MUTATIONS                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Purpose: Modify data (like HTTP POST/PUT/DELETE)              β”‚
β”‚  Side Effects: Creates, updates, or deletes data               β”‚
β”‚  Execution: Always sequential (one by one)                     β”‚
β”‚  Caching: Should not be cached                                 β”‚
β”‚                                                                 β”‚
β”‚  mutation CreateUser($input: CreateUserInput!) {               β”‚
β”‚    createUser(input: $input) {                                 β”‚
β”‚      id                                                         β”‚
β”‚      name                                                       β”‚
β”‚      email                                                      β”‚
β”‚    }                                                            β”‚
β”‚  }                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         SUBSCRIPTIONS                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Purpose: Real-time updates (like WebSocket)                   β”‚
β”‚  Side Effects: Establishes persistent connection               β”‚
β”‚  Execution: Long-lived connection                              β”‚
β”‚  Caching: Not applicable                                       β”‚
β”‚                                                                 β”‚
β”‚  subscription MessageAdded($chatId: ID!) {                     β”‚
β”‚    messageAdded(chatId: $chatId) {                             β”‚
β”‚      id                                                         β”‚
β”‚      text                                                       β”‚
β”‚      user { name }                                              β”‚
β”‚    }                                                            β”‚
β”‚  }                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Variables and Arguments Flow

GraphQL Request with Variables:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  {                                                              β”‚
β”‚    "query": "query GetUser($userId: ID!, $includeEmail: Boolean!) { β”‚
β”‚                user(id: $userId) {                              β”‚
β”‚                  name                                            β”‚
β”‚                  email @include(if: $includeEmail)              β”‚
β”‚                }                                                β”‚
β”‚              }",                                                β”‚
β”‚    "variables": {                                               β”‚
β”‚      "userId": "123",                                           β”‚
β”‚      "includeEmail": true                                       β”‚
β”‚    }                                                            β”‚
β”‚  }                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Variable Substitution:                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ $userId β†’ "123"                                             β”‚ β”‚
β”‚  β”‚ $includeEmail β†’ true                                        β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                              β”‚                                 β”‚
β”‚  Effective Query:                                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ user(id: "123") {                                           β”‚ β”‚
β”‚  β”‚   name                                                      β”‚ β”‚
β”‚  β”‚   email @include(if: true)  // Will be included            β”‚ β”‚
β”‚  β”‚ }                                                           β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ” Error Handling: Visual Guide

GraphQL has a structured approach to error handling:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      GraphQL Response                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  {                                                              β”‚
β”‚    "data": {        // Partial data (what succeeded)           β”‚
β”‚      "user": {                                                  β”‚
β”‚        "name": "John",                                          β”‚
β”‚        "email": null    // Failed field returns null           β”‚
β”‚      }                                                          β”‚
β”‚    },                                                           β”‚
β”‚    "errors": [      // Detailed error information              β”‚
β”‚      {                                                          β”‚
β”‚        "message": "Email service unavailable",                 β”‚
β”‚        "path": ["user", "email"],  // Location of error        β”‚
β”‚        "locations": [{"line": 4, "column": 5}],               β”‚
β”‚        "extensions": {                                          β”‚
β”‚          "code": "SERVICE_UNAVAILABLE",                        β”‚
β”‚          "timestamp": "2024-01-15T10:30:00Z"                  β”‚
β”‚        }                                                        β”‚
β”‚      }                                                          β”‚
β”‚    ]                                                            β”‚
β”‚  }                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Error Propagation Rules

Field Resolution Error Propagation:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                 β”‚
β”‚  Non-null field error β†’ Propagates up to parent                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ user {                                                      β”‚ β”‚
β”‚  β”‚   name!  ← Error here (non-null)                           β”‚ β”‚
β”‚  β”‚   email                                                     β”‚ β”‚
β”‚  β”‚ }                                                           β”‚ β”‚
β”‚  β”‚                                                             β”‚ β”‚
β”‚  β”‚ Result: user becomes null, error recorded                  β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                                 β”‚
β”‚  Nullable field error β†’ Field becomes null                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ user {                                                      β”‚ β”‚
β”‚  β”‚   name                                                      β”‚ β”‚
β”‚  β”‚   email  ← Error here (nullable)                           β”‚ β”‚
β”‚  β”‚ }                                                           β”‚ β”‚
β”‚  β”‚                                                             β”‚ β”‚
β”‚  β”‚ Result: email becomes null, error recorded, user remains   β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🎯 Our Implementation: Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  GraphQL-RS Architecture                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
β”‚  β”‚   HTTP Layer    β”‚    β”‚   Presentation  β”‚                    β”‚
β”‚  β”‚   (Axum/Warp)   │◄──►│     Layer       β”‚                    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β”‚                                   β”‚                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
β”‚  β”‚  Infrastructure β”‚    β”‚   Application   β”‚                    β”‚
β”‚  β”‚     Layer       │◄──►│     Layer       β”‚                    β”‚
β”‚  β”‚ β€’ Query Parser  β”‚    β”‚ β€’ Use Cases     β”‚                    β”‚
β”‚  β”‚ β€’ Schema Parser β”‚    β”‚ β€’ Services      β”‚                    β”‚
β”‚  β”‚ β€’ Lexer         β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚                            β”‚
β”‚                                   β”‚                            β”‚
β”‚                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
β”‚                         β”‚  Domain Layer   β”‚                    β”‚
β”‚                         β”‚ β€’ Entities      β”‚                    β”‚
β”‚                         β”‚ β€’ Value Objects β”‚                    β”‚
β”‚                         β”‚ β€’ Services      β”‚                    β”‚
β”‚                         β”‚ β€’ Events        β”‚                    β”‚
β”‚                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Request Flow in Our Implementation

HTTP Request β†’ GraphQL Runtime β†’ Response
     β”‚                 β”‚              β”‚
     β–Ό                 β–Ό              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   POST   β”‚    β”‚    Parse     β”‚    β”‚   JSON   β”‚
β”‚ /graphql │───▢│   Validate   │───▢│ Response β”‚
β”‚          β”‚    β”‚   Execute    β”‚    β”‚          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
                       β–Ό
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚   Our Rust Components    β”‚
                β”‚                          β”‚
                β”‚ 1. QueryParser          β”‚
                β”‚    β€’ Lexical Analysis    β”‚
                β”‚    β€’ Syntax Parsing      β”‚
                β”‚                          β”‚
                β”‚ 2. SchemaValidator       β”‚
                β”‚    β€’ Type Checking       β”‚
                β”‚    β€’ Rule Validation     β”‚
                β”‚                          β”‚
                β”‚ 3. QueryExecutor         β”‚
                β”‚    β€’ Field Resolution    β”‚
                β”‚    β€’ Data Fetching       β”‚
                β”‚                          β”‚
                β”‚ 4. ResponseBuilder       β”‚
                β”‚    β€’ Error Formatting    β”‚
                β”‚    β€’ JSON Serialization  β”‚
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸš€ What Makes GraphQL Powerful

1. Single Source of Truth

The schema serves as the single contract between frontend and backend teams.

2. Strong Type Safety

Every field, argument, and return type is explicitly defined and validated.

3. Introspection

GraphQL APIs are self-documenting through introspection queries.

4. Developer Experience

Tools like GraphQL Playground, Apollo Studio, and IDE extensions provide excellent DX.

5. Performance

🎯 Next Steps

Now that you understand GraphQL fundamentals, explore:

  1. Domain Model - How we structure our Rust implementation
  2. Schema Definition - Building type-safe GraphQL schemas
  3. Query Execution - How queries are processed and resolved
  4. Mutation Support - Data modification with sequential execution

This foundation will help you understand how each component works together to create a complete GraphQL server! πŸŽ‰

3. Queries

Clients specify exactly what data they need:

query GetUser {
  user(id: "123") {
    id
    name
    posts {
      id
      title
    }
  }
}

4. Mutations

Modify data on the server:

mutation CreateUser {
  createUser(input: {
    name: "John Doe"
    email: "john@example.com"
  }) {
    id
    name
  }
}

5. Subscriptions

Real-time data updates:

subscription PostCreated {
  postCreated {
    id
    title
    author {
      name
    }
  }
}

GraphQL Execution Model

1. Parsing

2. Validation

3. Execution

Key Benefits

  1. Single Endpoint: One URL for all data operations
  2. Precise Data Fetching: No over-fetching or under-fetching
  3. Strong Type System: Compile-time query validation
  4. Introspection: Self-documenting APIs
  5. Real-time: Built-in subscription support
  6. Versionless: Evolve APIs without breaking changes

GraphQL vs REST

Aspect GraphQL REST
Endpoints Single endpoint Multiple endpoints
Data Fetching Precise, client-controlled Fixed structure
Over-fetching Eliminated Common issue
Versioning Not needed Required
Caching Complex Simple (HTTP caching)
Learning Curve Steeper Gentler

Implementation Challenges

  1. Query Complexity: Preventing expensive nested queries
  2. N+1 Problem: Efficient data loading patterns
  3. Caching: More complex than HTTP caching
  4. File Uploads: Not part of core spec
  5. Security: Query depth and complexity attacks

Next Steps

Understanding these fundamentals is crucial for implementing a GraphQL server. In the next sections, we’ll dive into: