How GraphQL Works

GraphQL follows a clear request-response cycle. Understanding each step in this cycle removes all the mystery from how a query travels from your browser to the database and back.

The Four Layers of GraphQL

  ┌─────────────────────────────────────────────┐
  │  CLIENT  (Browser / Mobile App)             │
  │  Sends a GraphQL query as an HTTP POST      │
  └──────────────────┬──────────────────────────┘
                     │
  ┌──────────────────▼──────────────────────────┐
  │  GRAPHQL SERVER  (The entry point)          │
  │  Receives query, validates it against schema│
  └──────────────────┬──────────────────────────┘
                     │
  ┌──────────────────▼──────────────────────────┐
  │  RESOLVERS  (The worker functions)          │
  │  Each field in the query has a resolver     │
  │  that fetches the actual data               │
  └──────────────────┬──────────────────────────┘
                     │
  ┌──────────────────▼──────────────────────────┐
  │  DATA SOURCES  (DB, REST API, cache, etc.)  │
  │  Resolvers read from here and return data   │
  └─────────────────────────────────────────────┘

Step 1 – The Client Writes a Query

The client writes a GraphQL query describing the fields it wants. The query is plain text that looks like JSON but is not JSON. It travels to the server inside the body of an HTTP POST request.

  POST /graphql
  Content-Type: application/json

  {
    "query": "{ user(id: \"1\") { name email } }"
  }

Step 2 – The Server Parses the Query

The GraphQL server reads the incoming text query and builds an internal tree structure called an Abstract Syntax Tree (AST). Think of the AST as a map of all the fields the client asked for, organized in a hierarchy.

  Query text:              AST (internal tree):
  ──────────               ───────────────────
  {                        Query
    user(id:"1") {          └── user
      name                       ├── arg: id="1"
      email                      ├── name
    }                            └── email
  }

Step 3 – Validation Against the Schema

The server checks the query against the schema. If you ask for a field that does not exist, or pass the wrong type of argument, the server rejects the query immediately with a clear error. This happens before any database call, which prevents wasted work.

  Schema says:             Query asks for:        Result
  ────────────             ───────────────        ──────
  user { name, email }     user { name, phone }   ✗ Error: 
                                                  "phone" does
                                                  not exist

Step 4 – Resolvers Fetch the Data

For each field in the validated query, the server calls a resolver function. A resolver is a plain function that knows how to fetch data for its field. The resolver for user might run a database query. The resolver for name simply reads the name property from the user object already in memory.

Step 5 – The Response Is Assembled

The server collects all the resolver results and assembles them into a JSON object that mirrors the exact shape of the query. This response travels back to the client.

  Query shape:             Response shape:
  ────────────             ───────────────
  {                        {
    user {                   "data": {
      name                     "user": {
      email                      "name": "Alice",
    }                            "email": "alice@x.com"
  }                            }
                             }
                           }

Errors Travel Alongside Data

GraphQL returns errors inside the response body, not as HTTP error codes. A response can carry partial data and partial errors at the same time. The data key holds successful results and the errors key lists any problems that occurred.

  {
    "data": {
      "user": {
        "name": "Alice",
        "posts": null
      }
    },
    "errors": [
      {
        "message": "Posts service unavailable",
        "path": ["user", "posts"]
      }
    ]
  }

Key Points

  • GraphQL queries travel as HTTP POST requests to a single endpoint.
  • The server parses the query into a tree, then validates it against the schema.
  • Each field in the query is handled by a resolver function.
  • The response mirrors the exact shape of the query.
  • Errors appear inside the response body alongside any data that was successfully fetched.

Leave a Comment