Contact Us
24/7
Python BlogDjango BlogSearch for Kubernetes Big DataSearch for Kubernetes AWS BlogCloud Services
<< ALL BLOG POSTS

Doing the Homework on REST vs. GraphQL

|
February 7, 2023

Every once in a while, almost every software developer in the world has to investigate what technology to use when faced with a particular task at hand. Usually these technologies come in pairs. This time my concern — and the concern of the team I've been working with — was to suggest to our customer which technology to use for their project: REST or GraphQL.

REST (Representational State Transfer) is an API that conforms to a set of constraints. It is an architectural style — one needs to change a URL in order to retrieve different information. It supports GET, POST, PUT, PATCH, and DELETE HTTP requests; and JSON, XML, and YAML data formats.

There might be some concerns with over- or under-fetching since the output is always static. Naturally, there are some solutions to mitigate that. One can implement query parameters for the endpoint and this way control either filtering or a set of fields returned to a client.

In a way, GraphQL (Graph Query Language) is a response to the problems in REST. There is only one endpoint, and to get different information, one only needs to change the query. It only supports POST HTTP requests. For simple projects it adds “unnecessary” complexity that some teams might not like.

Usually, GraphQL is very good at resolving over- or under-fetching issues since it will only provide the fields requested in the query. Above all a lot of developers seem to like it in it is gaining more and more traction.

Representational state transfer (REST) is a dominant style for modern API architecture. According to Postman’s 2022 State of the API report, 89% of developers use REST. GraphQL is in fourth place at 38%, superseded by webhooks (35%) and SOAP (34%).

Who is using GraphQL

There is a wide variety of companies using GraphQL. This doesn’t necessarily mean they use it exclusively or instead of REST API. But they are definitely seeing great value in it, e.g.:

Comparing by Example

I will try to create a very simple example for each approach. Since I was doing research for a Django project, I will also implement it here. I will use a requirements.txt file with the following contents:

Django==4.1.7
djangorestframework==3.14.0
graphene-django==3.0.0

After that, we create our project:

mkdir rest-graphql-django
cd rest-graphql-django
python3 -m venv .venv
. .venv/bin/activate
pip install -U pip
pip install -r requirements.txt
django-admin startproject app .
./manage.py startapp api

I am going to use the api app to set up my example project.

In app/settings.py let’s add:

INSTALLED_APPS = [
    ...
    "django.contrib.staticfiles",
    "api.apps.ApiConfig",
    "graphene_django",
    "rest_framework",
]

Contents of the api/models.py:

from django.db import models


# Create your models here.
class Author(models.Model):

    first_name = models.TextField(max_length=255)
    last_name = models.TextField(max_length=255)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"


class Book(models.Model):

    title = models.TextField(max_length=255)
    year = models.IntegerField(default=0)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, null=True, blank=True)

    def __str__(self):
        return f"{self.title}"

REST example setup

Contents of the api/serializers.py:

from rest_framework import serializers

from api.models import Author
from api.models import Book


class AuthorSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Author
        fields = "__all__"


class BookSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Book
        fields = "__all__"

Contents of the api/views.py:

from api.models import Author
from api.models import Book
from api.serializers import AuthorSerializer
from api.serializers import BookSerializer
from rest_framework import viewsets


# Create your views here.
class AuthorViewSet(viewsets.ModelViewSet):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer


class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

GraphQL example setup

Contents of the api/schema.py:

import graphene
from graphene_django import DjangoObjectType

from api.models import Author
from api.models import Book


class AuthorType(DjangoObjectType):
    class Meta:
        model = Author
        fields = ("id", "first_name", "last_name")


class BookType(DjangoObjectType):
    class Meta:
        model = Book
        fields = ("id", "title", "year", "author")


class Query(graphene.ObjectType):
    hello = graphene.String(default_value="Hi!")

    authors = graphene.List(AuthorType)
    books = graphene.List(BookType)

    def resolve_authors(root, info):
        return Author.objects.all()

    def resolve_books(root, info):
        return Book.objects.all()


schema = graphene.Schema(query=Query)

In app/settings.py I need to also add:

GRAPHENE = {
    "SCHEMA": "api.schema.schema"
}

Finally, we need to update the app/urls.py file:

from django.contrib import admin
from django.urls import include
from django.urls import path
from graphene_django.views import GraphQLView
from rest_framework import routers

from api.views import AuthorViewSet
from api.views import BookViewSet

router = routers.DefaultRouter()
router.register(r"authors", AuthorViewSet)
router.register(r"books", BookViewSet)

urlpatterns = [
    path("", include(router.urls)),
    path("graphql", GraphQLView.as_view(graphiql=True)),
    path("admin/", admin.site.urls),
]


When running the app locally and navigating to http://127.0.0.1:8000/ we are able to see both endpoints: for authors and books. We can also navigate to each particular endpoint.

api.png

book.png

On the other hand, navigating to http://127.0.0.1:8000/graphql we will find our GraphiQL web interface to write the queries and get results.

graph1.png

graph2.png

In this simple example, we can see that we can fetch the data either way. Advantages and disadvantages of each approach have to be pondered on a case-by-case basis.

REST GraphQL

An architectural style largely viewed as a conventional standard for designing APIs


A query language for solving common problems when integrating APIs

Deployed over a set of URLs where each of them exposes a single resource 

Deployed over HTTP using a single endpoint that provides the full capabilities of the exposed service


Uses a server-driven architecture


Uses a client-driven architecture

Uses caching automatically

Lacks built-in caching mechanism


Supports multiple API versions

No API versioning required


Response output usually in XML, JSON, and YAML


Response output in JSON

Doesn't offer type-safety or auto-generated documentation, requires 3rd party software


Offers type-safety and auto-generated documentation

Simplifying work with multiple endpoints requires expensive custom middleware


Allows for schema stitching and remote data fetching



GraphQL enables clients to run queries and get exactly what they ask for. But if GraphQL API is not carefully designed, it can overwhelm the server. Too many fields and too many nested queries could eventually bring it down. In this case, the REST approach might be more suitable since you can set up multiple endpoints for various scenarios and fine tune the queries.

I guess it is also important to have in mind the development team when deciding which tool to use. If the team is not comfortable with a particular tool, it might be better not to use it in the first place.

I believe GraphQL is an alternative to REST, not a replacement or a successor. There is also no one-fits-all approach on whether to choose one against the other. A careful examination of pros and cons in your particular case will let you know what would fit best. There are a number of articles online that favor either REST or GraphQL. Sometimes the arguments are very good, but sometimes they’re not really convincing. In the end, it’s up to you to do your homework.

How can we assist you in reaching your objectives?
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.