Skip to main content
REST to GraphQL migration:
Pros, cons and gotchas
Alexey Ivanov, Evil Martians
Evil Martians
Evil Martians
—  GraphQL query language: Its data types and response format.
—  Difference in using REST API and GraphQL API.
—  What you need to be aware of before switch between them.
What is this talk about
5
—  «How to start» guide.
—  GraphQL server implementation details.
—  Apollo, Relay and other ways to works with queries on the client side.
What is this talk NOT about
6
Why GraphQL?
—  https://example.com/api/v1/users
—  https://example.com/api/v1/users/12
—  https://example.com/api/v1/articles
—  https://example.com/api/v1/articles/12
Multiple endpoints
CLASSIC REST API
8
—   POST https://example.com/api/v1/users
—   GET https://example.com/api/v1/users/12
—   DELETE https://example.com/api/v1/users/12
—   PUT https://example.com/api/v1/users/12
Different methods for them
CLASSIC REST API
9
GET https://example.com/api/v1/users?limit=10&sort=name
POST https://example.com/api/v1/users
{
"name": "Jane Doe",
/* 20 more fields */
}
Optional payload and params
CLASSIC REST API
10
GET https://example.com/api/v1/articles/12
{
"title": "Hedgehogs",
"dateCreated": "2019-12-01",
"content": "Five pages of text about hedgehogs",
/* 20+ more fields */
}
All possible fields in response
CLASSIC REST API
11
—   GET https://example.com/api/v1/main_page
—   GET https://example.com/api/v1/article_page
—   GET https://example.com/api/v1/category_page
Context-specific endpoints
PRACTICAL REST API
13
{
"currentUser": { /* ... */ },
"navigation": { /* ... */ },
"news": { /*...*/ },
"articleOfTheDay": {
"title": 'Title',
"snippet": 'Some text...'
}
}
All data filtered and in one place
PRACTICAL REST API
14
—  Tons of page and context specific queries
—  You need to change backend implementation every time frontend changes
—  Different endpoints for desktop and mobile devices
—  Hard to do split testing if different designs need different data
Problems
PRACTICAL REST API
15
—  What endpoints do you have
—  Which data each endpoint serve
—  What values can every field be set to
—  What types of errors can you get
—  What endpoints and fields are deprecated
REST API documentation
16
GraphQL
to the rescue
type Query {
currentUser: User
}
type User {
id: ID
name: String
}
Schema
HOW GRAPHQL WORKS
19
function Query_currentUser(request) {
return request.auth.user;
}
function User_name(user) {
return user.getName();
}
Resolvers
HOW GRAPHQL WORKS
20
Query
{
currentUser {
name
}
}
Result in JSON
{
"currentUser": {
"name": "Jane Doe"
}
}
Query only the fields you need
HOW GRAPHQL WORKS
21
{
currentUser {
name
}
news {
title
}
}
Single endpoint and query batching
HOW GRAPHQL WORKS
22
currentUser {
id
friends {
id
friends {
id
}
}
}
Links to other data
HOW GRAPHQL WORKS
23
{
user(id: "100") {
name
avatar
profileText
}
}
Params on any level
HOW GRAPHQL WORKS
24
{
user(id: "100") {
name
avatar(size: "100")
profileText(length: "50")
}
}
Params on any level
HOW GRAPHQL WORKS
25
{
author: user(id: "100") {
name
}
commenter: user(id: "101") {
name
}
}
Aliases
HOW GRAPHQL WORKS
26
{
user(id: "100") {
name
smallAvatar: avatar(size: "50")
bigAvatar: avatar(size: "100")
}
}
Params with aliases
HOW GRAPHQL WORKS
27
mutation ($name: String!) {
createUser(name: $name) {
id
name
}
}
Mutations
HOW GRAPHQL WORKS
28
—  DOCs are automatically generated from the type definitions
—  You can add description to any field or mark it as deprecated
—  Play with API using browser extension or GraphiQL
Automatic sandbox and docs
HOW GRAPHQL WORKS
29
GraphiQL demo
—  Subscriptions
—  Variables
—  Directives
—  Automatic validation
—  Reusable request fragments
Other cool things
HOW GRAPHQL WORKS
31
Cool, right?
Should
we migrate?
Well…
Can't do that:
{
currentUser {
*
}
}
Have to declare all fields you need
GRAPHQL GOTCHAS
35
currentUser {
id
friends {
id
friends {
id
}
}
}
Have to declare all fields you need
GRAPHQL GOTCHAS
36
{
"navigation": [{
"url": "/about",
"title": "About us",
"children": [
/* ... */
]
}]
No recursive structures
GRAPHQL GOTCHAS
37
{
articles {
id
author {
name
}
}
}
{
"articles": [{
"id": "1",
"author": {
"name": "Jane Doe"
}
}]
}
No normalized data
GRAPHQL GOTCHAS
38
{
"users" {
"1": { "id": "1", "name": "Jane Doe" }
},
"articles": {
"1": { "id": "1", "authorId": "1" }
}
}
No normalized data
GRAPHQL GOTCHAS
39
{
articles {
1: {
id
authorId
}
}
}
No normalized data
GRAPHQL GOTCHAS
40
{
currentUser { id name }
users {
name
occupation
}
}
Requires normalization on client
GRAPHQL GOTCHAS
41
{
"currentUser": { "id": "1", name: "Jane Doe" },
"users": [{
"name": "Jane Doe",
"occupation": "Software Engineer"
}]
}
Requires normalization on client
GRAPHQL GOTCHAS
42
mutation ($id: Id!, $data: UserData!) {
updateUser(id: $id, data: $data) {
id
name
occupation
}
}
Requires normalization on client
GRAPHQL GOTCHAS
43
{
"id": "1",
"name": "Jane Doe",
"occupation": "Software Engineer"
}
Requires normalization on client
GRAPHQL GOTCHAS
44
{
"users": {
"1": {
"id": "1",
"name": "Jane Doe",
"occupation": "Software Engineer"
}
}
}
Requires normalization on client
GRAPHQL GOTCHAS
45
{
"currentUser": "1",
"users": ["1", "2", "3", ...]
}
Requires normalization on client
GRAPHQL GOTCHAS
46
To be able to normalize you need to have __typename and id in every query:
{
currentUser {
__typename
id
name
}
}
Requires normalization on client
GRAPHQL GOTCHAS
47
Pros:
—  Automatically normalize/denormalize and merge data.
—  Can batch queries in one.
—  Give you bindings to React/Vue and other libraries.
Apollo and Relay
GRAPHQL GOTCHAS
48
Cons:
—  Large size of the libraries.
—  Not the most convenient API.
—  A lot of «magic» rules inside that are not always obvious.
—  To add or delete items to lists you need to edit their caches by hand.
—  Works better with some types of data structiores then with other.
Apollo and Relay
GRAPHQL GOTCHAS
49
—  Need to pretty much rewrite all buisness logic and data alyer from scratch.
—  Either use large libraries like Apollo or Relay or write own normalization layer.
—  Code for non-trivial mutations can became larger and harder to read then in
REST.
Cost of frontend migration
50
—  Starting new project? Use GraphQL and probably Apollo.
—   Existing project mostly reading data? Migrate and use GraphQL without
Apollo.
—   Existing project with simple mutations? Not sure, but if you decide to,
migrate and use GraphQL with Apollo.
—   Existing project with a lot of non-trivial mutations? You probably
shouldn't. And if you decide to, better write your normalization layer by hand.
Summary
51
Alexey Ivanov, Evil Martians
@iadramelk   evl.ms   @evilmartians
REST to GraphQL migration: Pros,
cons and gotchas
52