fbpx

Blogs from the Ranch

< Back to Our Blog

GraphQL versus REST

Avatar

Nathan Bennett

GraphQL is a new way for developers to think about APIs. GraphQL and REST paradigms can both be used to create scalable and useful APIs, but GraphQL has some alternative approaches that make a big difference for developers. The core components of each API strategy are approached differently. This blog post focuses on three key differences between REST and GraphQL that give GraphQL an edge, especially for developer productivity.

Be sure to check out our post, What is GraphQL? if you’d like a refresher.

No more over/under fetching

Resources are one of the key ideas in REST. For developers using REST, the approach is to identify each resource by a URL. By contrast, developers are generally expected to use a single endpoint for GraphQL APIs. An API using REST to allow access to a book resource may return something like the following when clients send a GET request to the /books/1 path:

{
  "title": "Timeless Laws of Software Development",
  "author": {
    "first_name": "Jerry",
    "last_name": "Fitzpatrick"
  },
  "illustrator": {
    "first_name": "Jennifer",
    "last_name": "Kohnke"
  },
  "id": 1,
  "url": "/books/1",
  "categories": ["software", "testing"]
}

Everything about the above response to the GET request was determined by the API. Any time developers want to fetch details about a book they can generally expect the same type of response using the /books/{id} endpoint.

GraphQL is very different when it comes to how it interprets the idea of resources. In GraphQL, the concept of a resource is generally expressed as a type using the GraphQL schema language. For the book API in the example above, GraphQL would express the book resource as a type:

type Book {
  id: ID
  title: String
  illustrator: Illustrator
  author: Author
  categories: [String]
}

The Book type describes the kind of data available but notably lacks a URL that specifies how to retrieve a particular book by id. While confusing if you are new to GraphQL, the reason for lacking a URL is because GraphQL separates resources from how they are retrieved. In practice, this means backend developers must specify a Query type that exposes the ability to fetch books instead of determining a URL pattern to expose as an endpoint. In addition to the Book type, adding the following replaces the concept of a /books/{id} endpoint in REST:

type Query {
  book(id: ID!): Book
}

To get details about any book resource, any client can request the Book resource and only specific fields they need for a book. Instead of querying via an endpoint, developers would send a GET request to the API that looks something like this:

/graphql?query={ book(id: "1") { title } }

Note that instead of specifying the resource in the URL, as with REST, the GraphQL request for a book resource is in a different format. Developers sending this query to a GraphQL endpoint (e.g. /graphql) would retrieve something like the following:

{
  "title": "Timeless Laws of Software Development"
}

The shape and size of the GraphQL query is determined by the nature of the request. Developers working on clients consuming a GraphQL API get the benefit of being able to decide what data they want from the API. If a developer wanted more data, such as the name of the illustrator of a book, then they would simply request those additional fields from the API.

Typed queries

GraphQL’s schema language allows for the API to specify types for every field associated with an object. In addition to some special types, it also supports specifying custom object types as well. Developers are prone to mistakes when developing clients for APIs, especially when documentation on the shape of an endpoint’s response is lacking. REST has some solutions for mapping endpoints to fluent interfaces such as TypedRest, but GraphQL’s schema language comes with a type system baked in. Tools can parse the types specified for return values from queries to make tooling that catches errors early.

For example, the query that was looked at earlier can be easily understood by developers and tooling:

type Query {
  book(id: ID!): Book
}

Developers new to this API simply need to investigate the Book object type to know what will be returned by the above query. More information can be provided for introspection in a description, and we’ll cover that in a moment.

The baked-in type system has extensive documentation and is also used by developers to create tools that prevent errors during development. Server-side tools such as Apollo Server use the type system for introspection and even allows developers to test and preview queries in a playground. VSCode has a plugin called Graphql for VSCode that provides linting, syntax highlighting, and even schema validation. To take full advantage of the power of GraphQL’s type system and typed queries out of the box all you need to do is reach for a plugin in your IDE.

Self-documenting nature

GraphQL’s schema language can be checked for validity. This allows developers to reference a GraphQL API’s schema as a source of truth. While poor naming of object types and fields is possible, good naming within a GraphQL schema results in APIs that are self-documenting. Naming is probably one of the most important things to get right in a GraphQL project because tools and developers rely on the type system to explain the shape and nature of the data they are requesting.

For REST APIs, Swagger is a good option for producing publishable documentation. However, GraphQL treats documentation as a first-class feature of its specification, meaning developers don’t need to reach for external documentation tools or generators. Up-to-date and accurate descriptions of fields and types can be pulled directly from the GraphQL schema! For example, a schema could be documented using CommonMark in code as follows:

"""
The representation for books available in the catalog
"""
type Book {
  "Unique identifer"
  id: ID
  "The name of the book as listed in the catalog"
  title: String
  "The illustrator listed in the catalog for the book"
  illustrator: Illustrator
  "The author listed in the catalog for the book"
  author: Author
  "The categories this book belongs to on the website"
  categories: [String]
}

"""
Represents an illustrator of a book
"""
type Illustrator {
  first_name: String
  last_name: String
}

"""
Represents an author of a book
"""
type Author {
  first_name: String
  last_name: String
}

type Query {
  """
  Retrieves a book by ID
  """
  book("The unique `ID` of a book" id: ID!): Book
}

The description feature of the GraphQL specification, well-named object types, and descriptive fields ensures the documentation for a GraphQL API is always publishable to tools and future developers.

For queries and mutations, developers can easily see what fields are available. Entire IDEs are being developed just for GraphQL as well that leverages the language’s support for introspection. GraphiQL is one such IDE developed by the GraphQL Foundation.

Now that we’ve looked at REST vs GraphQL, you might be wondering if GraphQL is something that you want to tackle with your next project. Check out Is GraphQL Right for My Project? to get a good idea of the questions you should ask prior to jumping in.

Avatar

Nathan Bennett

Not Happy with Your Current App, or Digital Product?

Submit your event

Let's Discuss Your Project

Let's Discuss Your Project