This episode dissects how GraphQL works under the hood: parsing, validation, and query execution, the main components such as SDL and resolvers, the three basic operations — query, mutation, and subscription — as well as gateway and federation architectural patterns.

In episode 1 you learned why GraphQL exists. Now it's time to understand how GraphQL works from the inside. Episode 2 dissects GraphQL's architecture and fundamental concepts thoroughly.
We'll trace the flow of a request from the client until data is returned: parsing, validation, and execution. Then we'll get to know the main components — schema, type system, resolvers, data sources, context, and the execution engine. Finally, we'll discuss the three basic operations and the architectural patterns used in industry, including gateways and federation.
Beyond understanding the technical flow, one principle will recur throughout this series: in GraphQL, the schema is the source of truth. Every GraphQL capability — validation, autocomplete, documentation, and execution — is rooted in the schema you write.
Every GraphQL operation goes through three stages inside the runtime:
query string -> parse -> validate -> execute -> JSON responseImportant consequence: GraphQL never executes a query that fails validation. That's why the schema must be defined precisely — the schema is both contract and guard.
To make this flow concrete, imagine a restaurant. The menu is the schema, the waiter is the parser that translates the order, and the kitchen is the resolver that prepares each dish. If an item isn't on the menu, the waiter rejects the order before it ever reaches the kitchen — exactly like GraphQL rejecting a query that doesn't match the schema.
You can see for yourself how a query is turned into an AST with node -e "const g=require('graphql');console.log(g.parse('{hello}'))". Notice that the parser works without needing to know the schema's contents — validation is what uses the schema, and it happens after parsing is done.
GraphQL executes resolvers in parallel when possible. Independent resolvers run concurrently via Promise.all, while nested resolvers wait for the parent to finish first because they need the parent's value. This understanding matters when optimizing performance in episode 19 and when dealing with the N+1 problem in episode 9.
SDL is the language for defining schemas. It's the heart of GraphQL:
type Query {
hello: String
users: [User]
}
type User {
id: ID!
name: String!
age: Int
}The entire type system is built from this schema. We'll dissect SDL and all the available types in depth in episode 3.
If the schema answers the question "what does it look like", the resolver answers "where does the data come from". Every field in the schema can have a resolver whose job is to fetch data from a data source — a database, REST API, or another service. Meanwhile, the context is an object shared with all resolvers within a single request, usually containing the logged-in user, database connections, and data loaders. You'll learn all the details in episode 6.
The execution engine is the runtime that ties everything together. It receives a query, validates it against the schema, then walks the AST and calls resolvers field by field. In the JavaScript ecosystem, the reference implementation is the graphql library derived from the specification. When you use Apollo Server later, you're actually running the execution engine on top of an HTTP server.
GraphQL defines three operation types, each mapping to a different root type:
Query type.Mutation type.Subscription type.type Query {
getPost(id: ID!): Post
}
type Mutation {
createPost(title: String!): Post
}
type Subscription {
postCreated: Post
}Important rule: query operations execute in parallel, while mutations execute serially. This guarantees that sequential mutations within one request each see the result of the previous mutation — we'll discuss this in episode 5.
The choice between query, mutation, and subscription isn't just a syntactic difference; it establishes a semantic contract. Both client and server know that a mutation changes state, so tooling can ask for confirmation before sending, and caching can be treated differently. These semantic nuances make a GraphQL API more expressive than a mere list of endpoints.
When an application grows into many services, you can place a GraphQL Gateway in front of those services. The gateway aggregates each service's schema into one global schema, so the client still interacts with a single endpoint. There are two main approaches: schema stitching and federation, which we'll cover in episode 22.
The simplest and most common pattern: GraphQL stands as an API layer between clients and data. Clients only know GraphQL, while behind it there can be a database, legacy REST APIs, or third-party services. This pattern is great for starting to adopt GraphQL without rewriting the whole architecture, and it becomes the foundation of the migration strategy in episode 47.
Key takeaways:
In the next episode, episode 3, you'll learn about the Schema Definition Language and Type System — scalar types, object types, input types, enums, interfaces, unions, plus list types and modifiers. This is the foundation that determines the shape of your entire GraphQL API, so make sure you stay focused!