GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data.
A GraphQL service is created by defining types and fields on those types, then providing functions for each field on each type.
1 | type Query { |
Along with functions for each field on each type:
1 | function Query_me(request) { |
Once a GraphQL service is running (typically at a URL on a web service), it can be sent GraphQL queries to validate and execute. A received query is first checked to ensure it only refers to the types and fields defined, then runs the provided functions to produce a result.
For example the query:
1 | { |
Fields
GraphQL is about asking for specific fields on objects.
GraphQL queries can traverse related objects and their fields, letting clients fetch lots of related data in one request, instead of making several roundtrips as one would need in a classic RESTFul architecture.
Arguments
In GraphQL, every field and nested object can get its own set of arguments, making GraphQL a complete replacement for making multiple API fetches. You can even pass arguments into scalar fields, to implement data transformations once on the server, instead of on every separately.
1 | { |
Arguments can be of many different types. GraphQL comes with a default set of types, but a GraphQL server can also declare its own custom types, as long as they can be serialized into your transport format.
Aliases
You can’t directly query for the same field with different arguments, so you need alias to rename the result
1 | { |
In the above example, the two hero fields would have conflicted, but since we can alias them to different names, we can get both results in one request.
Fragments
GraphQL includes reusable units called fragments. Fragments let you construct sets of fields, and then include them in queries where you need to.
1 | { |
Variables
When we start working with variables, we need to do three things:
Replace the static values in the query with
$variableNameDeclare
$variableNameas one of the variables accepted by the queryPass
variableName: valuein the separate, transport-specific(usually JSON) variables dictionary
1 | query HeroNameAndFriends($episode: Episode) { |
Now in our client code, we can simply pass a different variable rather than needing to construct an entirely new query.
Variable Definitions
The variable definitions are the part that looks like ($episode: Episode) in the query above. It works just like the argument definition for a function in a types language. It lists all of the variables, prefixed by $, followed by their type, in this case Episode.
All declared variables must be either scalars, enums, or input object types.
Variable Definition can be optional or required. In the case above, since there isn’t an ! next to the Episode type, it’s optional. But if the field you are passing the variable into requires a non-null argument, then the variable must be required.
Default Variables
Default variables can also be assigned to the variables in the query by adding the default value after the type declaration.
1 | query HeroNameAndFriends($episode: Episode = 'JEDI') { |
Directives
1 | query Hero($episode: Episode, $withFriends: Boolean!) { |
We needed to use a new feature in GraphQL called directive. A directive can be attached to a field or fragment inclusion, and can affect execution of the query in any way the server desires. The core GraphQL specification includes exactly two directives, which must be supported by any spec-compliant GraphQL server implementation:
@include(if: Boolean): Only include this field in the result if the argument is
true@skip(if: Boolean): Skip this field if the argument is
true
Mutations
If mutation field returns an object type, you can ask for nested fields. This can be useful for fetching the new state of an object after an update.
1 | mutation CreateReviewForEpisode ($ep: Episode!, $review: ReviewInput!) { |
Here the createReview returns the star and commentary fields of the newly created review.
Multiple fields in mutations
A mutation can contain multiple fields, just like a query. There’s one important distinction between queries and mutations, other than the name.
While query fields are executed in parallel, mutation fields run in series, one after the other. This means that if we send two incrementCredits mutations in one request, the first is guaranteed to finished before the second begins, ensuring that we don’t end up with a race condition with ourselves.
Inline Fragments
GraphQL include the ability to define interfaces and union types.
If you are querying a field that returns an interface or a union type, you will need to use inline fragments to access data on the underlaying concrete type.
1 | query HeroForEpisode ($ep: Episode!) { |
In this query, the hero field returns the type Character, which might be either a Human or a Droid depending on the episode argument. In the direct selection, you can ask for fields that exists on the Character interface such as name.
To ask for a field on the concrete type, you need to use a inline fragment with a type condition. Because the first fragment is labeled as ... on Droid, the primaryFunction field will only be executed if the Character returned from hero is of the Droid type.
Named fragments can also be used in the same way, since a named fragment always has a type attached.
Meta fields
Given that there are some situations where you don’t know what type you will get back from the GraphQL service, you need some way to determine how to handle that data on the client. GraphQL allows you to request __typename, a meta field, at any point in a query to get the name of the object type at that point.
1 | { |
In the above query, search returns a union type that can be one of three options. It would be impossible to tell apart the different types from the client without the __typename field.
Schemas and Types
Type System
GraphQL query language is basically about selecting fields on objects.
1 | { |
We start with a special ‘root’ object
We select the
herofield on thatFor the object returned by
hero, we select thenameandappearsInfields
Object Types and Fields
The most basic components of a GraphQL schema are object types, which just represent a kind of object you can fetch from your service, and what fields it has. In the GraphQL schema language, we might represent it like this:
1 | type Character { |
Characteris a GraphQL Type, meaning it’s a type with some fields. Most of the types in your schema will be object types.nameandappearsInare fields on theCharactertype. That means thatnameandappearsInare the only fields that can appear in any part of a GraphQL query that operates on theCharactertype.Stringis one of the built-in scalar typesString!means that the field isnon-nullable, meaning that the GraphQL service promises to always give you a value when you query this field.[Episode]!represents an array ofEpisodeobjects. Since it is also non-nullable, you can always expect an array ( with zero or more items) when you query theappearsInfield.
Arguments
Every field on a GraphQL object type can have zero or more arguments, for example the length field below:
1 | type Starship { |
All arguments are named.
The Query and Mutation Types
Most types in schema will just be normal object types, but there are two types that are special within a schema:
1 | schema { |
Every GraphQL service has a query type and may not have a mutation type. These types are the same as a regular object type, but they are special because they define the entry point of every GraphQL query.
1 | query { |
That means that the GraphQL service needs to have a Query type with hero and droid fields:
1 | type Query { |
Mutations work in a similar way - you define fields on the Mutation type, and those are available as the root mutation fields you can call in your query.
Scalar Types
Int: A signed 32-bit integerFloat: A signed double-precision floating-point valueString: A UTF-8 character sequenceBoolean: true or falseID: The ID Scalar type represents a unique identifier, often used to refetch an object or as the key for a cache. The ID types serialized in the same way as a String; However, defining it as anIDsignifies that it is not intended to be human-readable.
In most GraphQL service implementation, there is also a way to specify custom scalar types.
1 | scalar Date |
Enumeration Types
Also called Enums, enumeration types are a special kind of scalar that is restricted to a particular set of allowed values.
1 | enum Episode { |
This means that wherever we use the type Episode in our schema, we expect it to be exactly one of NEWHOPE, EMPIRE, JEDI.
Lists and Non-Null
Object types, scalars, and enums are the only kinds of types you can define in GraphQL, but when you use the types in other parts of the schema, or in your query variable declarations, you can apply additional type modifier that affects validation of those values.
Interfaces
An Interface is an abstract type that includes a certain set of fields that a type must include to implement the interface.
1 | // define |
Union Types
Union Types are similar to interfaces, but they don’t get to specify any common fields between the types.
1 | union SearchResult = Human | Droid | Starship |
Input Types
In GraphQL schema language, input types look exactly the same as regular object types, but with the keyword input instead of type:
1 | input ReviewInput { |
1 | mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) { |



