GraphQL vs REST—Can GraphQL replace REST?

GraphQL is a query language and runtime for APIs, intended to be a replacement for REST. GraphQL offers a more efficient and flexible way for building APIs and scaling. While REST has been (and still is) a popular way of exposing data to applications, the growing complexity and evolution of development have made it less viable in a range of scenarios.

Read on to see how GraphQL can be a suitable replacement for REST and is a game-changer in the API ecosystem and data aggregation.

Here are the points we’ll go over:

Benefits of using GraphQL instead of REST

REST and GraphQL are both ways of designing interfaces that provide access to data. But there are several differences.

GraphQL solves many of the demerits and inefficiencies of REST API architecture. The benefits of using GraphQL over REST are:

  • Eliminates the over-fetching and under-fetching problems.
  • Strong type system offers out-the-box validation and type checking.
  • Data fetching in a single network call saves valuable resources.
  • Streamlines development with fewer lines of code.
  • Flexible queries help to design pragmatic and client-oriented APIs.
  • Large, complex apps and services benefit largely from GraphQL’s ability to make complex queries.
  • Enables swift growth and evolution through faster product iterations.
  • GraphQL’s philosophy of data modeling offers valuable insights and data visualization.

Let’s go a bit deeper and try to understand the problems GraphQL solves and how it differs from REST.

Data fetching: Aggregating data using GraphQL versus REST

Data means nothing unless we put a label or context on it and use it for a specific purpose. That’s what data aggregation does—it collects relevant pieces from the massive units of data that sit inside databases and helps us discover and extract information.

Data aggregation significantly impacts us largely in our day-to-day lives. With data science and big data becoming powerful tools in data analysis for varying use-cases across different kinds of organizations, turning a fresh eye towards how we aggregate data is relevant like never before. The high availability of data sources in this information age has opened up a lot of opportunities. From preparing risk assessment strategies, gaining insights into customer interests in large and small businesses, to gathering medical data for accelerating healthcare systems, data aggregation is a step we can’t take lightly.

If we can improve upon the way we search for and collect data, we can add a major efficiency boost to how we gather information. GraphQL brings many improvements to the table in this regard that you should consider.

With a GraphQL query, you get the exact amount of data you want. GraphQL makes data aggregation effortless and effective. In a REST API, you’d aggregate data by sending requests to multiple endpoints.

For example, consider an application where users can post their photos and access them. Users have followers and the photos have likes and shares. To access user data, there could be a /user/<user_id> endpoint. Another endpoint like /user/<user_id>/photos would expose all the photos of a user. A third endpoint could be /user/<user_id>/followers that returns a list of followers of a user.

These endpoints could return the following data:

/user/<user_id>

{
    "user": {
        "id": "0x23cf",
        "username": "elizabeth",
        "name": "Elizabeth McNulty",
    }
}

/user/<user_id>/photos

{
    "photos": [
        {
            "category": "Selfie",
            "description": "Selfie with best friend while hiking",
            "likes": 10,
            "shares": 5,
        },
        {
            "category": "Nature",
            "description": "View from the top of the hill",
            "likes": 20,
            "shares": 7,
        }
    ]
}

/user/<user_id>/followers

{
    "followers": [
        {
            "id": "0xda93",
            "username": "john",
            "name": "John Steiner",
        },
        {
            "id": "0x269b",
            "username": "michelle",
            "name": "Michelle Williams",
        }
        ...
    ]
}

You need to dispatch three requests to three different endpoints to gather all the available data, all of which you might not need. Since these API endpoints have fixed data structures, client requirements aren’t respected and you end up with less or excessive data. You need to set up an extra layer of processing to get what you want out of these static payloads. REST by nature doesn’t allow enough flexibility in designing APIs that can closely follow client requirements.

A GraphQL query on the other hand is much more compact. There is only one GraphQL endpoint where you can send a single request asking for the information you need. The JSON response object you get fulfills your specified requirements, nothing more nothing less.

Take a look at the following GraphQL query that asks for a user’s username, category, and description of posted photos, and information on the most recent five followers:

query {
	User(id: "0x23cf") {
		username
		photos {
			category
			description
			likes
			shares
		}
		followers(last: 5) {
			username
		}
	}
}

The response strictly follows the body of the request:

{
    "data": {
        "User": {
            "username": "Alice",
            "photos": [
                {
                    "category": "Selfie",
                    "description": "Selfie with best friend while hiking",
                    "likes": 10,
                    "shares": 5,
                },
                {
                    "category": "Nature",
                    "description": "View from the top of the hill",
                    "likes": 20,
                    "shares": 7,
                },
            ],
            "followers": [
                {"username": "john"},
                {"username": "poly"},
                {"username": "michelle"},
                {"username": "alan"},
                {"username": "ash95"},
            ]
        }
    }
}

This way GraphQL solves the ubiquitous problem of over-fetching, where you end up with more data than what an application needs for a use case, as well as under-fetching, where a specific endpoint doesn’t provide enough data; as a consequence, you’re forced to call a second endpoint, giving rise to the n+1 problem.

These additional network requests put pressure on bandwidth. When dealing with a large amount of data, this could cause serious issues like increased latency and waste of resources.

With GraphQL, you only need to make a single request, and you get what you want in a single network call. This greatly improves efficiency in terms of data aggregation operations on large datasets. Due to less stress on bandwidth and minimal data transfer, GraphQL is an emergent choice for scenarios such as poor network conditions, low-powered devices, etc. The increasing usage and adoption of mobile and wireless devices can also benefit from GraphQL, helping build efficient applications and services for a variety of such platforms.

Development and evolution

Another drawback with REST is that it introduces extra layers of work regarding the evolution and scaling of applications.

Due to the static nature of REST, each endpoint in the API serves a fixed set of data, corresponding to the pages or views in our app. This is useful in the sense that for a particular view, you can retrieve all the information you need by hitting the corresponding endpoint. But this kills productivity and flexibility in the long term.

A sudden change on the client-side requires that the server-side also correspond to this change so that it can serve an appropriate response. If the application now requires more or less data, you might have no way but to add another endpoint.

Programmers need to go back and forth between client and server with every change that occurs in an application’s lifecycle. API maintenance could quickly become a major pain-point; breaking changes in the API could result in serving stale data to clients.

GraphQL being faithful to what an application asks for eliminates this problem. Changes on the client-side don’t require any extra adjustments on the backend, since the client can always specify what it needs in a GraphQL query.

This makes faster iterations and regular product updates possible and offers a great opportunity for exploring new ideas. You can incorporate user feedback and roll out and test new features without worrying about the overall productivity.

Analytics and monitoring

Monitoring APIs is crucial for getting insights into services and ensuring healthy operations. GraphQL API, due to its strict nature by design in receiving and serving requests compared to REST API, yields more benefits when you add monitoring and instrumentation tools.

Since clients specify exactly what information they want for their purposes, GraphQL enables a clearer and deeper understanding of data usage. This not only helps in maintaining and evolving APIs, but also provides valuable insights into customers, enabling fine control over business goals.

As we’ll later discuss, queries in GraphQL are handled by what’s called GraphQL resolvers. These are special functions that fetch appropriate data and send it back to the client. You can set up tests and monitor the performance of these functions to get useful analytics on your API’s response time and adopt necessary measures accordingly.

Schema and type system

The approach taken by GraphQL and REST in defining queries is quite different.

REST provides endpoints to handle each type of request. Simply put, a RESTful API is just a collection of endpoints serving fixed data from the database to serve the client’s requests. The data requirements of your application are tightly coupled with each of these endpoints.

GraphQL treats requests differently, using what’s called a schema. In the GraphQL schema, you define the data requirements of your application. The application can query any type of data described within the schema. GraphQL leverages a strong type system in its Schema Definition Language (SDL) that enables you to break down your application data into smaller components called data objects. The schema describes each of these objects, the relationships among them, and in doing so what queries can be made.

For our example application, a simple schema could look like this:

type Photo {
	category: String!
	description: String!
	postedBy: User!
	likes: Int!
	shares: Int!
}
type User {
	username: String!
	name: String!
	photos: [Photo]
	followers: [User]
}

The app deals with only two types of data: users and photos.

Each type has associated fields describing the types in detail.

The relation between the User type and Photo type is that a user can have photos, and each photo belongs to a single user account, indicated by the photos and postedBy fields respectively. The value of photos is an array of Photo objects, and the postedBy field indicates which user posted the photo.

GraphQL models data as graphs, hence the name GraphQL. Unlike relational database models where data is represented in rows and columns, and document-oriented database systems where data is stored and queried as JSON-like documents, a GraphQL schema represents data as a collection of nodes and edges.

If you want a closer look at data modeling using relational databases compared to graph databases like Dgraph, check out our course Graph Data Models 101.

In the above schema, the objects User and Photo are nodes of the data graph, related to each other (edge) in a way. The relationships can be unidirectional, or bi-directional like in our example.

Taking entities and drawing relationships among them is a powerful way of not just representing data, but also visualizing it.

The schema gives a clear and concrete structure to the API and what it exposes to a client. The schema only defines the data entities, not the actual data sent over the network upon receiving a request. It’s up to the client to compose a query asking for what actual data it needs. The schema is like a contract between the client and the server that fleshes out the types and their relationships with one another, and the client can ask the server for whatever data it needs belonging to those types.

Each GraphQL query is interpreted against the schema. The queries are satisfied by special functions called GraphQL resolvers. These functions generate appropriate responses to GraphQL queries.

Because of a definite schema structuring what data a client can access, developers on the front-end and backend don’t need to further communicate. The front-end team can set up the necessary mocking to test the client-side and work on the user experience.

In REST, even without any sudden changes in the client’s data requirements, the front-end team has to wait for the backend team to finish setting up an endpoint. GraphQL’s declarative nature saves time and boosts productivity by facilitating communication among developers.

Determining whether GraphQL or REST are best for your needs

Choosing between GraphQL and REST for your API needs is a highly subjective concern. But there are a couple of general outlines and scenarios we can talk about that can reduce the decision load from your mind.

GraphQL offers many improvements over REST, but it’s not without its cons. You need to consider them against your scenario before jumping into a decision.

Performance with complex queries: Being a client-oriented system, a scenario might arise where a single GraphQL query contains deeply nested fields. Resolving such a complex or large query slows down the performance. In this case, even at the cost of multiple network calls, REST might be a better solution depending on whether or not you can afford to maintain and keep your GraphQL API performant under such conditions.

It’s possible to set up mechanisms to handle problematic cases such as this, like specifying query depths (how many fields you can access at a time through a query), recursion prevention, etc.

However, you don’t have to worry about performance if you’re using Dgraph. Dgraph being a native GraphQL database, has an industry-proven record of maintaining millisecond query response time and consistent performance, even while serving complex queries with deep traversals.

Caching: GraphQL lacks built-in caching support. Caching is necessary to avoid re-fetching and keeping frequently requested data at hand; this reduces server load.

REST, having multiple endpoints, achieves this using the built-in HTTP caching. GraphQL only has one endpoint serving different queries, so this type of caching isn’t supported. Hence the client needs to set it up on its own, depending on an external library. For example, GraphQL clients like Apollo have caching support built-in.

Working with files: GraphQL doesn’t support operations like file uploading, as there’s no mention of it in the GraphQL specification. Unlike GraphQL, REST leverages HTTP methods for file operations and you can upload any content by making a POST or PUT request.

Even so, there are several options to allow this using GraphQL:

  • Setting up a separate REST endpoint solely for uploading files: This adds an additional layer as now there are two servers to manage
  • Using Base64 encoding: After encoding the file content with Base64, you can send it as a GraphQL mutation. This makes the request quite large, and the encoding-decoding process adds extra complexity.

Apart from these facts, your decision will also depend on the type of application you’re building.

If it’s a small app dealing with relatively consistent data, then REST would be the best choice. On the other hand, for complex applications dealing with a large amount of data that’s rapidly changing, GraphQL would be the obvious choice. GraphQL is a very powerful tool when it comes to data unification, and so can be adopted in a distributed architecture. For companies having multiple API platforms with evolving data across a wide spectrum, GraphQL can take away many of the complexities and offer better maintenance.

As mentioned before, GraphQL is also suitable for scenarios where you want to ensure efficiency and speed under small or limited resources, like building services for mobile, IoT, and wearable devices.

GraphQL has built-in support for adding real-time features to applications that deal with constantly changing data through GraphQL subscriptions, making it a great choice for applications such as real-time messaging platforms, location-aware services, etc (we have an article on how GrpahQL subscriptions work that’ll give you a hands-on walkthrough of this feature).

How to get started using GraphQL

You can get started using GraphQL by reading our ultimate guide or going through our GraphQL tour.

If you want to jump right in, you can go through our courses on how to build GraphQL apps in React and Vue, dive into our docs, or simply get started with your own backend on Dgraph Cloud.

Dgraph Cloud is our fully-managed GraphQL backend service, built for the cloud, where we and our community have built a diverse range of apps. You can sign up and get started for free.

Now, let’s take a step back and look at what things you need to set up for starting a GraphQL project, and how Dgraph can help you with that.

A GraphQL server processes the requests coming in and generates proper responses. But how?

As you might’ve guessed from our discussion, using the GraphQL schema and resolver functions.

After you have a GraphQL server set up, for example using Apollo Server, and have given it your schema and resolvers, you need a GraphQL client that interfaces your application with the server and handles stuff like sending requests to the server endpoint, caching, and stateful data management. Apollo Client is a popular library for that.

Normally you’d have to write those resolver functions yourself, which can become a repetitive process and a huge undertaking for complex applications. With Dgraph, you don’t have to worry about that.

Dgraph gives a fully functional, production-ready GraphQL API just from your GraphQL schema (don’t take our word for it—take a look at the case studies demonstrating Dgraph’s proven strength in production environment). With Dgraph, you don’t have to get caught up in the grunt work of setting up the tooling. Our platform brings ease in building GraphQL applications, giving developers a quick start on their ideas and a painless, enjoyable experience.

In our GraphQL guide, we try to answer some of the questions on topics surrounding GraphQL and Dgraph. If you’re interested in a deeper dive into what Dgraph brings to the GraphQL ecosystem, you can check out Dgrpah Cloud overview and a curated glossary of some GraphQL and Dgraph terms.

Ready to start building? Flex your fingers and go check out our tutorials at Dgraph learn, which will take you from GraphQL basics to creating an app in less than four hours. Using various GraphQL tools in the ecosystem (like Apollo Client), you’ll learn how to model your application data in GraphQL and build full-stack applications like a message-board app, in React and Vue, harnessing the power of Dgraph Cloud.

Our docs on GraphQL cover everything regarding Dgraph’s GraphQL implementation, including a quick start to set you up for a quick test run.

We post frequent updates on our blog, recording our journey as we go forward. So feel free to browse through and check back from time to time for new content.