A Quick Guide to GraphQL for REST developers

A Quick Guide to GraphQL for REST developers

This is a really quick guide to GraphQL for REST developers. It's was prompted by a comment on the #believeinserverless Discord channel.

TLDR;

Endpoints

GraphQL, unlike REST, only has one endpoint. It's usually called /graphql and it accepts an HTTP POST request. The post body is a JSON object that looks like

{
  "query": "...",
  "operationName": "...",
  "variables": { "someVariable": "someValue", ... }
}

The response is then

{
  "data": { ... },
  "errors": [ ... ]
}

Queries and Mutations

GraphQL has three type of operation with the main two being query and mutation.

Query

A query is used when you want to fetch data. Your query is going to look something like:

{
  query FetchCustomer($id: ID) {
    customer(id: $id) {
      name
      email
      address {
        street
        city
        state
        country
      }
    }
  }
}

This is a query with the operation named FetchCustomer that uses a variable id to find the customer. It then returns the fields name and email from the customer and street, city, state and country from the customers address.

Coming from a REST API the idea of specifying the fields you want might seem strange but this is the way. In the REST world this response is usually predetermined with the API developer. The other thing that might seem odd is being able to content objects and fetch related data. In this case we traversed from the customer to the address. With a REST API I may have needed to make two API calls to different endpoints.

What you get back in the data field is a JSON object with the data in the same structure you requested.

{
  "data": {
    "customer": {
      "name": "John Smith",
      "email": "john@example.com",
      "address": {
        "street": "1 Australia St",
        "city": "Sydney",
        "state": "NSW",
        "country": "Australia"
      }
    }
  }
}

Before proceeding it's worth pointing out that GraphQL has nullable and non-nullable types. Let's assume that address was nullable and there wasn't an address. What would happen? GraphQL returns null and doesn't try to fetch the fields for address so you get

{
  "data": {
    "customer": {
      "name": "John Smith",
      "email": "john@example.com",
      "address": null
    }
  }
}

Mutation

Mutations are used when you want to update data. They look similar to queries but have mutation instead of query.

{
  mutation CreateCustomer($input: CreateCustomerInput) {
    id
    name
    email
    address {
      street
      city
      state
    }
  }
}

My CreateCustomer assumes I have defined a model CreateCustomerInput somewhere and that the result is customer record. Like the query example I need to tell it what data I want returned.

How do I know what to send?

The GraphQL API will have a schema. This schema may be accessible from the /graphql endpoint using introspection. Tools often use this to provide strong typing for queries.

The good news is that a well designed schema is usually easy to navigate once you see the documentation from the introspection. Unfortunately many developers, especially building internal API's, put minimal though into their schema and the result can be a disaster.

Well designed schemas all follow a naming pattern (which one doesn't matter) and there tends to be strong parallels between GraphQL and what the equivalent REST API would have been. Let's assume we use the pattern resource + action.

RESTGraphQLType
GET /customerscustomersquery
POST /customerscustomerCreatemutation
GET /customers/:idcustomer(id)query
PUT /customers/:idcustomerUpdate(id, other)mutation
DELETE /customers/:idcustomerDelete(id)mutation
POST /customers/:id/activatecustomerActivate(id)mutation

Subscriptions

Queries and mutations allow you to fetch data but what if you want to be notified when data changes? For that GraphQL has subscription.

The subscription operation looks like queries and mutations but your are actually telling the server to push changes to you when they occur. This is commonly done by setting up a websocket connection so that the server can push data to you in response to mutations.

Where next?

This has been a super fast guide to GraphQL for REST developers. The goal wasn't to teach you everything about GraphQL but just give you enough information that you can have a reasonable conversation with special person in your life who won't shut up about how wonderful GraphQL is. BTW: They're right!

If you want to learn more a good starting point is How to GraphQL.