What is GraphQL?
GraphQL is a query language for APIs and a server-side runtime to fulfill those queries. GraphQL was created in 2012 and open-sourced by Facebook in 2015. It has rapidly grown in popularity, and tech companies such as Github, Shopify, Stripe, and Twitter have adopted it in recent years. Today the GraphQL Foundation oversees the GraphQL specification.
One of the critical advantages of GraphQL is the reduction of over-fetching of data. With GraphQL, developers can retrieve only the data they need, reducing the amount of unnecessary data transfer and the need to implement additional endpoints or complex query parameters.
GraphQL works with a single endpoint to retrieve existing data using queries and modify existing data using mutations. It also supports real-time updates and subscriptions, making building responsive and engaging user interfaces much simpler. That makes GraphQL especially powerful for front-end developers who want to develop apps faster.
GraphQL terminology - Schema, Types, Resolvers
This section describes the GraphQL terminology an API developer encounters when developing with GraphQL, such as:
- GraphQL Schema and Types
- GraphQL Queries
- GraphQL Mutations
- GraphQL Subscriptions
- GraphQL Resolvers
GraphQL Schema and Types
Being strongly typed is another critical advantage GraphQL APIs have over classical RESTful APIs. A GraphQL server can validate and enforce the structure of queries, mutations, and subscriptions before executing them. The GraphQL Schema is defined using the "GraphQL schema language" - it is similar to the query language and allows developers to define object types and object fields in a language-agnostic way.
Essential components of a GraphQL schema are:
- Object types
- Object fields
- The query, mutation, and subscription root types
- Enumeration types
- Input types
- Union types
Most types in a GraphQL schema will be object types that represent objects
of an application, such as User,
Account, Order, Event,
or similar. Each object type has one or more fields representing
properties like id, amount, name,
age, createdAt, email,
Here are examples of object types in products you might know:
- Facebook: Friend, Post, Message, Event, Page, Group.
- Airbnb: Listing, Host, Guest, Trip, Experience.
- Slack: Team, Member, Channel, Message, Reaction, Thread.
- Intercom: Customer, Teammate, Message, Conversation, Article.
A GraphQL server validates queries against the schema as query requests come in and executes attached query resolvers if successful. A client can retrieve information about a schema via introspection.
Queries are GraphQL operations that allow fetching data from the server. The query defines which object(s) and field(s) to return from the data source. A GraphQL API developer declares queries as fields of the root query type. GraphQL queries are the equivalent of HTTP GET requests in a REST API.
For the server to know which data to return from the server, a GraphQL API developer attaches and implements resolvers for each query. The GraphQL server projects the results retrieved from the data source onto the specified query fields validating and enforcing the defined query structure. Query resolvers will run in parallel to ensure the best possible performance. Clients can batch queries in a single HTTP request to retrieve results for multiple object types at once.
A GraphQL API developer declares mutations as fields of the root mutation type for writing, updating, or deleting data. GraphQL Mutations are the equivalent of HTTP POST, PUT, PATCH, and DELETE requests in a REST API.
To mutate data on the server, a GraphQL API developer attaches and implements mutation resolvers for each declared mutation. Similar to queries, the client calling a mutation defines which fields must be contained in the response when executed successfully. Batching mutations in a single request will run them sequentially.
A GraphQL API developer can use GraphQL Subscriptions to get real-time updates from the server. To achieve that, the client subscribes to mutation events that occur on the server. A mutation event can represent writing, updating, or deleting data on the server. GraphQL Subscriptions enable real-time or reactive features for an application.
A client establishes a persistent WebSocket connection to the server for retrieving mutation events through GraphQL Subscriptions. A WebSocket link stays open until either the client or the server terminates it.
In the previous section, we already learned about resolvers. Resolvers are doing the work of resolving GraphQL requests through executing code. Some examples could be validating query input parameters, retrieving data from a single or multiple data sources, handling permission-based access control, projecting query fields onto retrieved data attributes, or even requesting data from other APIs.
GraphQL allows you to attach a GraphQL resolver to any object type field of a GraphQL schema. This powerful concept allows developers to retrieve data from multiple sources at once. Note that the GraphQL standard does not provide direction on how to store data or which programming language to use. So, API developers can build APIs with whatever method they prefer. The GraphQL specification will ensure they function in predictable ways.
Discovering a GraphQL API
GraphQL is introspective, which allows developers to query the schema of a GraphQL API to learn about its types and fields. Thus the introspection query enables developers to discover the available GraphQL queries, mutations, subscriptions, object types, and object fields of a GraphQL API. Therefore, the ability to introspect allows the community to build developer tools for GraphQL. But on the other hand, introspection could become a security risk without access control because potential attackers can understand a GraphQL API well by running an introspection query.