More power to API clients
with GraphQL
Yann Simon - @simon_yann
Who am I
• Yann Simon, backend developer at commercetools
• in the last years, worked with REST APIs:
• for micro-services
• public APIs
Let’s build a
REST API
Let’s build an
e-commerce API
Let’s build an
e-commerce API
surprise surprise
GET /products/45
GET /products/45
{

"id": "45",

"name": "running shoes",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

}
GET /products/45
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

}

}
GET /products/45
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

},

"variants": [

{

"description": "black color",

"price": {

"centAmount": 3600,

"currencyCode": "USD"

}

},

{

"description": "red color",

"price": {

"centAmount": 3500,

"currencyCode": "USD"

}

}

]

}
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

},

"variants": [

{

"description": "black color",

"price": {

"centAmount": 3600,

"currencyCode": "USD"

}

},

{

"description": "red color",

"price": {

"centAmount": 3500,

"currencyCode": "USD"

}

}

]

}
OR?
GET /products/45
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"id": "3",

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

},

"variantIds": [ "23", "18" ]

}
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"id": "3",

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

},

"variantIds": [ "23", "18" ]

}
GET /products/45/variants/23
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"id": "3",

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

},

"variantIds": [ "23", "18" ]

}
GET /products/45/variants/23
{

"id": "23",

"description": "black color",

"price": {

"centAmount": 3600,

"currencyCode": "USD"

}

}
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"id": "3",

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

},

"variantIds": [ "23", "18" ]

}
GET /products/45/variants/23
GET /products/45/variants/18
{

"id": "23",

"description": "black color",

"price": {

"centAmount": 3600,

"currencyCode": "USD"

}

}
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"id": "3",

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

},

"variantIds": [ "23", "18" ]

}
GET /products/45/variants/23
GET /products/45/variants/18
{

"id": "23",

"description": "black color",

"price": {

"centAmount": 3600,

"currencyCode": "USD"

}

}
{

"id": "18",

"description": "red color",

"price": {

"centAmount": 3500,

"currencyCode": "USD"

}

}
More data, maybe unused
or
more requests?
Let’s build this API
with GraphQL
Demo
With GraphQL
• the client decides which fields are needed
With GraphQL
• the client decides which fields are needed
{

product(id: "45") {

name

masterVariant {

description

price {

centAmount

currencyCode

}

}

variants {

description

price {

centAmount

currencyCode

}

}

}

}
With GraphQL
• the client decides which fields are needed
{

product(id: "45") {

name

masterVariant {

description

price {

centAmount

currencyCode

}

}

variants {

description

price {

centAmount

currencyCode

}

}

}

}
With GraphQL
• the client decides which fields are needed
{

product(id: "45") {

name

masterVariant {

description

price {

centAmount

currencyCode

}

}

variants {

description

price {

centAmount

currencyCode

}

}

}

}
{

"data": {

"product": {

"name": "running shoes",

"masterVariant": {

"description": "white",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

},

"variants": [

{

"description": "white",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

},

{

"description": "black",

• exactly the data the client needs
• in one request
{

p45: product(id: "45") {

name

}



p54: product(id: "54") {

name

canBeCombinedWith {

id

name

}

}

}
• exactly the data the client needs
• in one request
{

p45: product(id: "45") {

name

}



p54: product(id: "54") {

name

canBeCombinedWith {

id

name

}

}

}
• exactly the data the client needs
• in one request
{

p45: product(id: "45") {

name

}



p54: product(id: "54") {

name

canBeCombinedWith {

id

name

}

}

}
{

"data": {

"p45": {

"name": "running shoes"

},

"p54": {

"name": "basketball shirt",

"canBeCombinedWith": [

{

"id": "46",

"name": "basketball shoes"

},

{

"id": "58",

"name": "basketball T-shirt"

}

]

}

}

}
• exactly the data the client needs
• in one request
{

p45: product(id: "45") {

name

}



p54: product(id: "54") {

name

canBeCombinedWith {

id

name

}

}

}
{

"data": {

"p45": {

"name": "running shoes"

},

"p54": {

"name": "basketball shirt",

"canBeCombinedWith": [

{

"id": "46",

"name": "basketball shoes"

},

{

"id": "58",

"name": "basketball T-shirt"

}

]

}

}

}
• exactly the data the client needs
• in one request
m
obile
friendly
With GraphQL
• the client has more power
{

product(id: "45") {

variants(master: false, limit: 10, offset: 20) {

price {

centAmount

}

}

}

}

• and the server can be more generic
Introspection
{

__type(name: "product") {

fields {

name

}

}

}

{

"data": {

"__type": {

"fields": [

{

"name": "id"

},

{

"name": "name"

},

{

"name": "masterVariant"

},

{

• the schema is used:
• to validate the queries (server & maybe client)
• for introspection
• for documentation
API evolution
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

}

}
API evolution
GET /products/45
{

"id": "45",

"name": "running shoes",

"masterVariant": {

"description": "white color",

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

}

}
{

"id": "45",

"names": {

"en": "running shoes",

"fr": "godasses pour courir vite"

},

"name": "running shoes",

"masterVariant": {

"descriptions": {

"en": "white color",

"fr": "couleur blanche"

},

"description": "white color",

"prices": {

"us": {

"centAmount": 3900,

"currencyCode": "USD"

},

"fr": {

"centAmount": 3400,

"currencyCode": "EUR"

}

},

"price": {

"centAmount": 3900,

"currencyCode": "USD"

}

}

}
Can we remove a
deprecated field?
Let’s modify our
GraphQL based API
Demo
With GraphQL
• a field can be deprecated
• still valid for a query
• not in the schema anymore
• the server can track if a field is used
• the field can be removed when not used anymore
REST vs GraphQL?
• REST is here to stay
• simple
• widely used
• GraphQL
• different approach
• solve some limits of REST
ecosystem
• used in Facebook’s native apps in production since 2012
• open source in July 2015
• specification
• backend agnostic
• implementation in different languages
• nodejs, java, scala, ruby, php and many more
• front-end frameworks based on GraphQL like relay
So you want to try it?
• https://learngraphql.com/
• create an account on https://admin.sphere.io/
• you can create a project with sample data
• try GraphQL with this account on https://
impex.sphere.io/graphiql
Thanks for your attention
Yann Simon - @simon_yann

Introduction to GraphQL at API days

  • 1.
    More power toAPI clients with GraphQL Yann Simon - @simon_yann
  • 2.
    Who am I •Yann Simon, backend developer at commercetools • in the last years, worked with REST APIs: • for micro-services • public APIs
  • 3.
  • 4.
  • 5.
    Let’s build an e-commerceAPI surprise surprise
  • 6.
  • 7.
    GET /products/45 {
 "id": "45",
 "name":"running shoes",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 }
  • 8.
  • 9.
    GET /products/45 {
 "id": "45",
 "name":"running shoes",
 "masterVariant": {
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 }
 }
  • 10.
  • 11.
    GET /products/45 {
 "id": "45",
 "name":"running shoes",
 "masterVariant": {
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 },
 "variants": [
 {
 "description": "black color",
 "price": {
 "centAmount": 3600,
 "currencyCode": "USD"
 }
 },
 {
 "description": "red color",
 "price": {
 "centAmount": 3500,
 "currencyCode": "USD"
 }
 }
 ]
 }
  • 12.
    GET /products/45 {
 "id": "45",
 "name":"running shoes",
 "masterVariant": {
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 },
 "variants": [
 {
 "description": "black color",
 "price": {
 "centAmount": 3600,
 "currencyCode": "USD"
 }
 },
 {
 "description": "red color",
 "price": {
 "centAmount": 3500,
 "currencyCode": "USD"
 }
 }
 ]
 } OR?
  • 13.
  • 14.
    GET /products/45 {
 "id": "45",
 "name":"running shoes",
 "masterVariant": {
 "id": "3",
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 },
 "variantIds": [ "23", "18" ]
 }
  • 15.
    GET /products/45 {
 "id": "45",
 "name":"running shoes",
 "masterVariant": {
 "id": "3",
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 },
 "variantIds": [ "23", "18" ]
 } GET /products/45/variants/23
  • 16.
    GET /products/45 {
 "id": "45",
 "name":"running shoes",
 "masterVariant": {
 "id": "3",
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 },
 "variantIds": [ "23", "18" ]
 } GET /products/45/variants/23 {
 "id": "23",
 "description": "black color",
 "price": {
 "centAmount": 3600,
 "currencyCode": "USD"
 }
 }
  • 17.
    GET /products/45 {
 "id": "45",
 "name":"running shoes",
 "masterVariant": {
 "id": "3",
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 },
 "variantIds": [ "23", "18" ]
 } GET /products/45/variants/23 GET /products/45/variants/18 {
 "id": "23",
 "description": "black color",
 "price": {
 "centAmount": 3600,
 "currencyCode": "USD"
 }
 }
  • 18.
    GET /products/45 {
 "id": "45",
 "name":"running shoes",
 "masterVariant": {
 "id": "3",
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 },
 "variantIds": [ "23", "18" ]
 } GET /products/45/variants/23 GET /products/45/variants/18 {
 "id": "23",
 "description": "black color",
 "price": {
 "centAmount": 3600,
 "currencyCode": "USD"
 }
 } {
 "id": "18",
 "description": "red color",
 "price": {
 "centAmount": 3500,
 "currencyCode": "USD"
 }
 }
  • 19.
    More data, maybeunused or more requests?
  • 20.
    Let’s build thisAPI with GraphQL Demo
  • 21.
    With GraphQL • theclient decides which fields are needed
  • 22.
    With GraphQL • theclient decides which fields are needed {
 product(id: "45") {
 name
 masterVariant {
 description
 price {
 centAmount
 currencyCode
 }
 }
 variants {
 description
 price {
 centAmount
 currencyCode
 }
 }
 }
 }
  • 23.
    With GraphQL • theclient decides which fields are needed {
 product(id: "45") {
 name
 masterVariant {
 description
 price {
 centAmount
 currencyCode
 }
 }
 variants {
 description
 price {
 centAmount
 currencyCode
 }
 }
 }
 }
  • 24.
    With GraphQL • theclient decides which fields are needed {
 product(id: "45") {
 name
 masterVariant {
 description
 price {
 centAmount
 currencyCode
 }
 }
 variants {
 description
 price {
 centAmount
 currencyCode
 }
 }
 }
 } {
 "data": {
 "product": {
 "name": "running shoes",
 "masterVariant": {
 "description": "white",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 },
 "variants": [
 {
 "description": "white",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 },
 {
 "description": "black",

  • 25.
    • exactly thedata the client needs • in one request
  • 26.
    {
 p45: product(id: "45"){
 name
 }
 
 p54: product(id: "54") {
 name
 canBeCombinedWith {
 id
 name
 }
 }
 } • exactly the data the client needs • in one request
  • 27.
    {
 p45: product(id: "45"){
 name
 }
 
 p54: product(id: "54") {
 name
 canBeCombinedWith {
 id
 name
 }
 }
 } • exactly the data the client needs • in one request
  • 28.
    {
 p45: product(id: "45"){
 name
 }
 
 p54: product(id: "54") {
 name
 canBeCombinedWith {
 id
 name
 }
 }
 } {
 "data": {
 "p45": {
 "name": "running shoes"
 },
 "p54": {
 "name": "basketball shirt",
 "canBeCombinedWith": [
 {
 "id": "46",
 "name": "basketball shoes"
 },
 {
 "id": "58",
 "name": "basketball T-shirt"
 }
 ]
 }
 }
 } • exactly the data the client needs • in one request
  • 29.
    {
 p45: product(id: "45"){
 name
 }
 
 p54: product(id: "54") {
 name
 canBeCombinedWith {
 id
 name
 }
 }
 } {
 "data": {
 "p45": {
 "name": "running shoes"
 },
 "p54": {
 "name": "basketball shirt",
 "canBeCombinedWith": [
 {
 "id": "46",
 "name": "basketball shoes"
 },
 {
 "id": "58",
 "name": "basketball T-shirt"
 }
 ]
 }
 }
 } • exactly the data the client needs • in one request m obile friendly
  • 30.
    With GraphQL • theclient has more power {
 product(id: "45") {
 variants(master: false, limit: 10, offset: 20) {
 price {
 centAmount
 }
 }
 }
 }
 • and the server can be more generic
  • 31.
    Introspection {
 __type(name: "product") {
 fields{
 name
 }
 }
 }
 {
 "data": {
 "__type": {
 "fields": [
 {
 "name": "id"
 },
 {
 "name": "name"
 },
 {
 "name": "masterVariant"
 },
 {
 • the schema is used: • to validate the queries (server & maybe client) • for introspection • for documentation
  • 32.
    API evolution GET /products/45 {
 "id":"45",
 "name": "running shoes",
 "masterVariant": {
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 }
 }
  • 33.
    API evolution GET /products/45 {
 "id":"45",
 "name": "running shoes",
 "masterVariant": {
 "description": "white color",
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 }
 } {
 "id": "45",
 "names": {
 "en": "running shoes",
 "fr": "godasses pour courir vite"
 },
 "name": "running shoes",
 "masterVariant": {
 "descriptions": {
 "en": "white color",
 "fr": "couleur blanche"
 },
 "description": "white color",
 "prices": {
 "us": {
 "centAmount": 3900,
 "currencyCode": "USD"
 },
 "fr": {
 "centAmount": 3400,
 "currencyCode": "EUR"
 }
 },
 "price": {
 "centAmount": 3900,
 "currencyCode": "USD"
 }
 }
 }
  • 34.
    Can we removea deprecated field?
  • 35.
  • 36.
    With GraphQL • afield can be deprecated • still valid for a query • not in the schema anymore • the server can track if a field is used • the field can be removed when not used anymore
  • 37.
    REST vs GraphQL? •REST is here to stay • simple • widely used • GraphQL • different approach • solve some limits of REST
  • 38.
    ecosystem • used inFacebook’s native apps in production since 2012 • open source in July 2015 • specification • backend agnostic • implementation in different languages • nodejs, java, scala, ruby, php and many more • front-end frameworks based on GraphQL like relay
  • 39.
    So you wantto try it? • https://learngraphql.com/ • create an account on https://admin.sphere.io/ • you can create a project with sample data • try GraphQL with this account on https:// impex.sphere.io/graphiql
  • 40.
    Thanks for yourattention Yann Simon - @simon_yann