Skip to content
Language:en Author:Laborci Gergely
api

GraphQL: Schema, Resolvers and Field Selection

Objectives

By the end of the lesson, you can explain the basic idea of GraphQL, the role of the resolver and the N+1 problem, the question of query cost, and characterise it along the seven aspects.

Why is it needed?

If many clients with different needs ask for the same data, endpoints with a fixed response shape either return too much or need too many calls (6.3). GraphQL addresses the problem of letting the client choose which fields it requests.

What is GraphQL?

According to graphql.org, GraphQL enables "flexible, versionless APIs" with a strong type system. The schema describes with types the data and operations available to the client; in a query the client states exactly the fields it needs. The server produces the values of the fields with resolvers, possibly from several data sources or services.

The schema is not an automatic mirror of the database: it describes concepts meant for the consumer. The fields of a type may come from three different data owners. Stating the requested fields can reduce overly large representations, but does not by itself guarantee a cheap query.

The kinds of operations: a query reads, a mutation changes state, a subscription delivers several results over time. According to the specification a subscription operation has exactly one root field; the specification does not fix the carrying protocol (it mentions HTTP only as an example), so the concrete transport, authentication and reconnection are given by the contract of the solution used.

One endpoint and the status code

According to graphql.org a GraphQL server typically receives all requests on a single URL (usually /graphql). POST must be supported for queries and mutations; GET can be used for queries only. A response may contain data and errors at once. According to the specification, if errors is present while data is not missing, the errors can be field errors; according to graphql.org, if data is not null, the response can be 2xx even when there are errors, because HTTP has no "partial success" status. The client must therefore interpret a partial result as well.

Resolvers and N+1

A list query can return twenty items; if each item has a data-source request for one of its fields, the result is one initial request and twenty more. This is the N+1 problem. The solution of graphql.org is batching: requests gathered over a short time are merged into one request (for example with a DataLoader-like tool).

flowchart LR
  C["Client query"] --> G["GraphQL endpoint"]
  G --> R["Resolvers"]
  R --> B["Batch"]
  B --> S1["Data source 1"]
  B --> S2["Data source 2"]

Cost and caching

A query valid according to the types can start many data-source calls or a large data set. According to graphql.org, complex operations can overload the data sources, so pagination, limiting depth and breadth, and query-complexity analysis protect them. GraphQL is cacheable like any parameterised API; GET queries can be cached, and for big queries a "persisted query" (sending a hash) can be used.

Characteristics

Aspect GraphQL
Direction Request–response; with a subscription also from the server side
Initiator The client
Connection persistence Query/mutation: per request; subscription: depends on the transport
Latency One request–response path, but fan-out on the server
Load Depends on the complexity of the query; it must be limited
Fault tolerance Partial result (data + errors)
When it fits Many kinds of clients, different field needs, complex read interfaces
When it does not A simple internal command interface; strongly cached resource reads

Common misconceptions

Statement Clarification
"GraphQL is always faster." Fewer client requests, but fan-out on the server is possible.
"GraphQL replaces REST." Different trade-offs; they can coexist.
"A subscription is always WebSocket." The specification does not fix the carrying protocol.
"HTTP 200 means there is no error." The response may contain errors too.

In short

  • GraphQL is based on schema and field selection: the client says what it requests.
  • Behind the resolvers fan-out and N+1 may occur; batching reduces them.
  • The cost of a query must be limited.
  • The response may be partial; the HTTP status alone does not say everything.

Review questions

  1. What is the N+1 problem, and what reduces it?
  2. Why must the depth and complexity of a query be limited?
  3. What does it mean that a response can contain data and errors at the same time?

Learning resources

Prerequisites (2)

  • synchronous and asynchronous communication
  • communication contract

Teaches (1)

  • GraphQL