DEV Community

Cover image for Why GraphQL is Gaining Adoption
Yusuf Mubaraq
Yusuf Mubaraq

Posted on

Why GraphQL is Gaining Adoption

Introduction

In the early days of web development, APIs enabled dynamic applications, yet they eventually became a source of significant challenges. As modern applications continue to grow in complexity, developers face mounting challenges in moving the right data between clients and servers quickly and efficiently. The introduction of REST (Representational State Transfer) APIs over two decades ago simplified how systems communicated by organizing resources into clear endpoints and using standard HTTP methods.

The REST API is a widely accepted convention for building web services. It is lightweight, fast and language-agnostic. But it isn't without its problem. A major one is over-fetching and under-fetching: clients may end up retrieving more information than what is required.

For example, suppose you call the /users endpoint to get a list of users. This may return additional information such as the user address and email which is not part of your request. There are scenarios where a single API call does not return enough data, which in turn leads to the invocation of more API calls.

REST APIs also lacked a schema and type system; clients were often unaware of the kinds of data that would be returned from the endpoints, which resulted in multiple rounds of communication between the frontend and the backend. This had long been a major pain point for developers until the unbelievable happened. The introduction of GraphQL.

What is GraphQL?

Imagine you're at a party where the menu says, "serve yourself". Here, you have the freedom to choose whatever meal type and quantity you're interested in. This is the exact idea behind GraphQL. The Graph Query Language, developed by Facebook was launched internally in 2012 and became open-sourced in 2015. A powerful query language for APIs, unlike REST, that allows you to request the specific data you need.

It gives power to the client to decide on what information it needs. GraphQL is language-agnostic, meaning it doesn't depend on the programming language you use to implement it.

Let's take a look at an example of how to fetch data from a GraphQL server:

query GetPosts {
  posts {
    id
    title
    content
  }
}
Enter fullscreen mode Exit fullscreen mode

In the example above, the query keyword tells GraphQL that you're sending a read request, while the GetPosts is just the name given to the query. Inside the query, the root field of posts tells the server what top-level piece of data you want to fetch. Inside the post object, you specified the exact type of data you want it to return which are the id, title and content. This returns the below result

{
  "data": {
    "posts": [
      {
        "id": "1",
        "title": "Getting Started with GraphQL",
        "content": "GraphQL is a query language for APIs and a runtime for    executing those queries."
      },
      {
        "id": "2",
        "title": "Understanding Queries",
        "content": "A query in GraphQL lets you ask for exactly the data you need."
      }
    ]
  }
}

Enter fullscreen mode Exit fullscreen mode

The above returns the exact data you requested. This is the beauty of GraphQL, it doesn't go above or below the specified instructions.

GraphQL Building Blocks

There are few terms you'll often come across and use while working with GraphQL. These are:

  • Schema and Types
  • Queries and Mutation
  • Resolver

Schema and Types
A schema in GraphQL is like a container that houses all the information your API can provide. Inside that container are fields, and each field is defined by a type that describes the shape of the data.

Query and Mutation
These are used to fetch data from the server. Query never change data; they only return what the schema allows. Mutation on the other hand, is similar to Create, Update, and Delete operation in REST API. While query only read data, mutations allow you to make changes. Let's check out example below:

//Query Example

type Query {
  posts: [Post]
}
//creates a Query type with one field, posts, which returns a list of Post objects.

//Mutation Example

type Mutation {
  language(id:ID): Language
}
//It creates a Mutation type with one field called language.
//The field takes an argument id of type ID and returns a Language object.
Enter fullscreen mode Exit fullscreen mode

Resolver
Resolvers play a key role in handling the logic for retrieving the data requested by a client. Each resolver function corresponds to a specific field in your GraphQL schema, deciding how and where to fetch that field’s data.

const resolvers = {
  Query: {
    posts: () => {
      return [
        { id: 1, title: "First Post", content: "Hello World" },
        { id: 2, title: "Second Post", content: "GraphQL is awesome!" },
      ];
    },
  },
};

//Here, the posts resolver runs whenever a client queries for posts, and it returns an array of post objects.
Enter fullscreen mode Exit fullscreen mode

Benefits of GraphQL

Avoids Over-fetching and Under-fetching
GraphQL solved a major problem faced by developers before its arrival. It ensured the API consumer only ask for what they need instead of getting a huge bulk of data, which not only reduce the payload size but also makes the application faster.

Strongly Typed
GraphQL is strongly typed, which means every piece of data in your API has a clear, predefined type. This makes it easier for clients to know the exact type of data they'll get back.

Realtime capabilities
GraphQL isn’t limited to just fetching or updating data, it can also handle Realtime updates through a feature called subscriptions. A subscription is similar to query or mutation but its used to listen to real-time events. For example, you're building a chat app, with subscription, your client can listen for new messages or notifications instantly.

Limitations of GraphQL

GraphQL is a powerful query language for APIs, offering flexibility and efficiency in data fetching. However, it comes with certain limitations that developers should consider when deciding its suitability for a project.

Difficult Optimisation
The fact that GraphQL gives clients the power to define and shape data makes caching and optimising queries difficult. Unlike REST, where each endpoint has a predictable response size, GraphQL queries can vary widely in complexity.

The N+1 Problem
The N+1 problem in GraphQL happens when your server has to make one initial request to fetch a list of items, and then an additional request for each item in that list to get related data. For example, if you query for a list of posts along with the author of each post, the server might first run one query to get all the posts and then run another query for each post to fetch its author. As the number of posts grows, the number of database calls increases which can quickly lead to serious performance issues if not optimised.

Conclusion

GraphQL has transformed how developers build and consume APIs by solving long-standing problems like over-fetching, under-fetching, and rigid endpoints. This matters today because modern applications demand faster performance, and a better developer experience. Its rise also connects to broader industry trends, such as the shift toward microservices, the growth of frontend frameworks that need efficient data fetching, and the push for real-time capabilities in web and mobile apps. Although REST APIs are still the most widely used, GraphQL has also been adopted by a growing number of big tech companies such as Netflix, GitHub, Shopify, and others, showing its increasing relevance and impact on the way modern APIs are designed.

Top comments (0)