Request Lifecycle
You now know what a schema and a query are. The final foundation is understanding what happens between sending a query and receiving a response. A GraphQL server processes every request in three ordered phases: parse, validate, and execute. Knowing these phases tells you exactly where and why a request can fail.
The three phases
Section titled “The three phases”sequenceDiagram participant C as Client participant P as Parse participant V as Validate participant E as Execute (resolvers) participant D as Data sources C->>P: query text P->>V: AST (grammar OK) Note over V: check AST against the schema V--xC: errors array if a field is invalid (no resolver runs) V->>E: validated AST E->>D: call resolvers, walk the query D-->>E: field values E-->>C: response shaped like the query
1. Parse
Section titled “1. Parse”The server receives the query as plain text and turns it into a structured tree called an Abstract Syntax Tree (AST). This phase only checks grammar — are the braces balanced, is the syntax well-formed? A missing closing brace or a stray comma fails here, before the schema is even consulted.
2. Validate
Section titled “2. Validate”Now the server compares the AST against the schema. This is where the type system earns its keep. The validator confirms that every field you selected actually exists on its type, that arguments have the right types, that you did not request scalar fields with a sub-selection, and dozens of other rules. If validation fails, the server rejects the request and returns an errors array — and crucially, no resolver runs. The query never touches your data or business logic.
3. Execute
Section titled “3. Execute”Once a query is parsed and validated, the server executes it by walking the AST and calling a resolver for each field. Execution starts at a root type (Query, Mutation, or Subscription) and descends field by field. Each resolver returns a value; if that value is an object type, the engine recurses into its selected sub-fields, calling their resolvers in turn. The returned values are assembled into a response whose shape mirrors the query.
Validation rejects an invalid field
Section titled “Validation rejects an invalid field”The best way to feel the difference between validation and execution is to watch validation catch an error. The runner below sends a query that asks for a field, colour, which does not exist on the Book type. Press Run: the schema is valid and the resolver is ready, but the request never reaches it. Instead the response is an errors array explaining the problem.
Read the output carefully. There is no data for the book; instead you get an errors array whose message says that colour cannot be queried on type Book, complete with the line and column where it appears. This is the validate phase doing its job. Fix the query — change colour to year — and run it again to watch the request sail through validation and into execution, returning real data.
Common mistakes
Section titled “Common mistakes”Business logic directly in the resolver
Symptoms:
- a resolver mixes SQL queries, validation, auth checks, and business rules together
- hard to test — a resolver’s unit test has to mock the database
- Fix: separate data fetching from business logic — keep resolvers thin
No error boundary in the resolver
Symptoms:
- a resolver throws an unhandled error and fails the whole query
- the client cannot tell which field failed and which succeeded
- Fix: handle errors deliberately in the resolver — return null or throw a GraphQL error
💡 Real-world examples
Apollo Server:
- plugin hooks (
parsingDidStart,validationDidStart,executionDidStart) let you track every phase (Apollo Server plugin event reference)GraphQL Yoga:
- uses the Envelop plugin system, which intercepts every phase of the lifecycle (Yoga docs)
- used for tracing, auth, and rate limiting in the pipeline