i GraphQL- the future of APIs – All things in moderation

GraphQL- the future of APIs

REST APIs are REST-in-Peace APIs: use GraphQL for your APIs

When the first time I started using django REST framework for my project, I’m so happy using it to create my backend service. But a problem is when I want to show information about an user has many information related to others object like: posts, comments, likes, etc. What should I do ? I had to create many request to fetch them. Get them all with 1 request what does that sound ? It’s a one of features graphql can solve for you. OK, let’s start!

I’m going to show the problems you face with REST and the reasons you should fall in love with graphql.

What is REST ?

If you are not fammiliar with REST, here a short defintion for you. In REST APIs, the server defines a specific set of resources that a client can request, and these resources are defined by unique URLs. For example, in the API for a generic microblogging platform, the URL /users/1 may denote the first user in the system, /user/1/posts/ could return a collection of all posts that user has written, and /users/1/posts/123 could return a single post.

What’s wrong with REST ?

The biggest problem with REST APIs is the nature of multiple endpoints. These require clients to do multiple round-trips to get their data.

REST APIs are usally a collection of endpoints, where each endpoint represents a resource. So whent a client needs data from multiple resources, it needs to perform multiple round-strips to a REST API to put together the data it needs.

In a REST API, there is no client request language. Clients do not have control over what data the server will return. There is no language through which they can do so. More accurately, the language avaiable for clients is very limited.

For example, the READ REST API endpoints are either:

  • GET /ResouceName – to get a list of all the records from that resource, or
  • GET /ResourceName/ResourceID – to get the single record identified by that ID.

A client can’t, for example, specify wich fields to select for a record in that resource. That information is in the REST API service itself and the REST API service will always return all of the fields regardless of which ones the client actually needs. GraphQL’s tern for this problem is over-fetching of information that’s not needed. It’s a waste of network and memory resources for both the client and server.

One other bog problem with REST APIs is versioning. If you need to support multiple versions, that usually means new endpoints. this leads to more problems while using and maintaining those endpoints and it might be the cause of code duplication on the server.

The REST APIs problems mentioned above are the onse sepecific to what GraphQL is trying to solve.

What is GraphQL ?

GrraphQL is a query language for your API, and a server-side runtime for executing querie by using a type system you define for your data. GraphQL isn’t tied to nay specific database or storage engine and is instead backed by you existing code and data.

How does a GraphQL server turn a query into a response ?

GraphQL queries

GraphQL queries have a very simple structure and are easy to understand. Take this one:

{
    subcribers(publication: "hydrasky"){
        name
        email
    }
}

It doesn’t take a rocket scientist to figure out that this query would return the names and e-mails of all subcribers of our publiccation. If we build an API for it. Here’s what the response would look like:

{
  subscribers: [
    { name: "Jane Doe", email: "[email protected]" },
    { name: "John Doe", email: "[email protected]" },
    ...
  ]
}

Notice how the shape of the response is almost the same as that of the query. The client-side of GraphQL is so easy, it’s practically self-explanatory!

But how about the server? Is it more complicated? It’s turns out that GraphQL servers are quite simple, too.

Schema and Resolve Functions

Every GraphQL server has two core parts that determine how it works: a schema and resolve functions.

The schema: The schema is a model of the data that can be fetched through the GraphQL server. It defines what queries clients are allowed to make, what types of data can be fetched from the server, and what the relationships between these types are. For example:

In GraphQL schema notation, it look like this:

type Author {
  id: Int
  name: String
  posts: [Post]
}

type Post {
  id: Int
  title: String
  text: String
  author: Author
}

type Query {
  getAuthor(id: Int): Author
  getPostsByTitle(titleContains: String): [Post]
}

schema {
  query: Query
}

This shema is quite simple: it states the application has three types Author, Post and Query. The third type Query is just there to mark the entry point into the schema. Every query has to start with one of its fields: getAuthor or getPostsByTitle. You can think of them sort of like REST endpoints, except more powerful.

Author and Post reference each other. You can get from Author to Post through the Author’s “post” field, and you can get from Post to Author through the Post’s”author” field.

The schema tells the server what queries clients are allowed to make, and how differenct types are related, but there is one critical piece of information that it doesn’t contain: where the data for each type comes from!
That’s what resolve functions are for.

Resolve Functions

Resolve functions are like little routers. The specify how the types and fields in the schema are connected to variour backends, answering the questions “How do I get the data for Authors?” and “Which backend do I need to call with what arguments to get the data for Posts?”.

GraphQL resolve functions can contain arbitray code, which means a GraphQL server can to talk to any kind of backend, even other GraphQL servers. For example, the Author type could be stored in a SQL database, while Posts are store in MongoDB, or even handled by a microservice.

Perhaps the greatest feature of GraphQL is that it hides all of the backend complexity from clients. No matter how many backend your app uses, al the client will see is a single GraphQL endpoint with a simple self-documenting API for you application.

Here’s an example of two resolve function:

class Query(AbstractType):
    category = relay.Node.Field(CategoryNode)
    all_categories = DjangoFilterConnectionField(CategoryNode)

    ingredient = relay.Node.Field(IngredientNode)
    all_ingredients = DjangoFilterConnectionField(IngredientNode)
Query execution-step by step

Alright, now that you know about schema and resolve functions, let’s look at the execution of an acutual query.

Side note: The code below is for GraphQL-JS, the Javascript reference implementation of GraphQL, but execution model is the same in all GraphQL servers I know of.

At the end of this section, you’ll understand how a GraphQL server uses the schema and resolve functions together to execute the query and produce the desired result.

Here’s a query that works with the schema introduced eariler. It fetches an author’s name, all the posts for that author, and the ame of the author of each post.

{
  getAuthor(id: 5){
    name
    posts {
      title
      author {
        name # this will be the same as the name above
      }
    }
  }
}

Side note: If you look closely, you will notice that this query fetches the name of the same author twice. I’m just doing that here to ilustrate GraphQL while keeping the schema as simple as possible.

Here are the three high-level steps the servers takes to respond to the query:

  1. Parse
  2. Validate
  3. Execute
Step1: Parsing the query

First, the server parses the string and turns it into an AST- an abstract syntax tree. If there are any syntax errors, the server will stop execution and return the syntax error to the client.

Step2: Validation

A query van be syntactically correct, but still make no sense, just like the following English sentence is syntactically correct, but doesn’t make any sense: ” The sand left through the idea”.

The validation stage makes sure that the query is valid given the schema before execution starts. It checks things like:
* is getAuthor a field of the Query type ?
* does getAuthor accept an argument named id ?
* Are name and posts fields on the type reuturned by getAuthor?

Step 3: Execution

If validation is passed, the GraphQL server will execute the query.

Every GraphQL query has the shape of a tree–i.e. it is never circular. Execution begins at the root of the query. First, the executor calls the resolve function of the fields at the top level-in this case just getAuthor — with provided parameters. It waits until all these resolve functions have returned a value, and then proceeds in a cascading fashing down the tree. If a resolve function returns a promise, the executor will wait until that promise is resolved.

GraphQL resouces

graphql.org – an official website of graphql community
awesome-graphql– Awesome list of GraphQL & Relay

graphql-resources – A collection of blog posts, videos, courses, podcasts, projects about graphQL

Conslusion

For now, many company adopt graphql in their product, it’s pretty easy to understand and apply. It’s solved all the problems REST-APIs can’t. So, let’s enjoy it !

Leave a Reply