Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
From REST to GraphQL
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Marc-Andre Giroux
September 06, 2016
Programming
1.3k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
From REST to GraphQL
Marc-Andre Giroux
September 06, 2016
More Decks by Marc-Andre Giroux
See All by Marc-Andre Giroux
It Depends - Examining GraphQL Myths & Assumptions
xuorig
0
140
So you Want to Distribute your GraphQL Schema?
xuorig
4
880
So you Want to Distribute your GraphQL Schema?
xuorig
0
690
GraphQL Schema Design @ Scale
xuorig
5
2.2k
Continuous Evolution of GraphQL Schemas @ GitHub
xuorig
3
2.2k
GraphQL à Shopify
xuorig
0
290
Exploring GraphQL
xuorig
0
310
GraphQL @ Shopify
xuorig
6
1.8k
GraphQL on Rails
xuorig
2
400
Other Decks in Programming
See All in Programming
Inside Stream API
skrb
1
800
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
1
470
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
290
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
240
Even G2とAWSで推しのエージェントを召喚しよう!
har1101
1
130
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2.3k
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
310
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
260
dRuby over BLE
makicamel
2
390
Snowflake Summitでの新機能 CoCo / CoWork / snowflake-summit-2026-overall-what-new-coco
tatsuhiro
1
190
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.3k
Creating Composable Callables in Contemporary C++
rollbear
0
170
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
740
Unsuck your backbone
ammeep
672
58k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
52k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
210
For a Future-Friendly Web
brad_frost
183
10k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Faster Mobile Websites
deanohume
310
32k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Building the Perfect Custom Keyboard
takai
2
800
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
450
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.1k
Transcript
From REST to GraphQL Marc-Andre Giroux @__xuorig__
About me
None
A simple UI component
None
What kind of data is needed?
Cart Product ProductImage
Reusable endpoints (REST)
/carts/1 /products/1 /products/2 /products/3 /product_images/1 /product_images/2 /product_images/3
Too many round trips!
/carts/1?expand=products
/carts/1?fields=products(name, description, price)
/carts/1?fields=products/name,description,price
Custom Endpoints
/cart_with_all_the_stuff_i_need
None
/cart_with_all_the_stuff_i_need /cart_version_2_with_all_the_things /cart_with_products_and_images /cart_with_products_and_images_with_price_and_taxes my_tightly_coupled_custom_endpoint_including_only_the_things_i_need_bla_bla_bla_bla /cart_with_products_and_images_with_price_and_taxes_but_no_description /cart_with_products_and_images_with_price_and_taxes_but_no_description_v2
None
Server Client Updates a view Creates a new view Product
view v2 Product model changes Update endpoints Create new endpoint
GraphQL
What GraphQL is NOT
What GraphQL IS
{ myShop { name } } Field Selection Set
{ myShop { name } } Lexed Parsed Validated Executed
{ “myShop” { “name”: “GitHub” } }
{ myShop { name } }
{ myShop { name } }
None
{ shop(id: 1) { name } }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
{ “myShop”: { “name”: “Full Stack Fest Shop” “location” {
“city”: “Barcelona” “address”: “Av. Diagonal 547” } “products”: [{ “name”: “Conference Ticket” “price”: 500000 }, { “name”: “Cool T-Shirt” “price”: 20000 }] } }
Type System
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
type QueryRoot { myShop: Shop shop(id: Int): Shop }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
type Shop { name: String location: Address products(orderby: OrderEnum): [Product]
} enum ProductOrderEnum { PRICE, POPULARITY, ALPHABETICAL }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
type Address { city: String address: String }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
type Product { name: String price: Int }
Fragments
{ myShop { name location { city address } products(orderby:
POPULARITY) { id name price } } }
None
{ myShop { name location { city address } products(orderby:
POPULARITY) { id name price } } }
fragment productFields on Product { id name price }
{ myShop { name location { city address } products(orderby:
POPULARITY) { ...productFields } } }
query Fragment Fragment Fragment Fragment
Introspection
query { __schema { … } }
Static Validation Code Generation IDE Integration Auto Documentation
None
None
Resolving fields
type Product { name: String price: Int }
ProductType = GraphQL::ObjectType.define do name "Product" description “A product sold
at a shop” # … end
field :name do type types.String resolve -> (obj, args, ctx)
{ obj.name } end
field :price do type types.Int resolve -> (obj, args, ctx)
do obj.subtotal + obj.taxes + obj.shipping_price end end
field :price do type types.Int resolve -> (obj, args, ctx)
do obj.subtotal + obj.taxes + obj.shipping_price end end
POST /graphql
Mutations
mutation { createProduct(name: “Nice Mug”, price: 10000) { id name
} }
Drawbacks and solutions
N+1 Queries
field :image do type ImageType resolve -> (product, args, ctx)
do product.image end end field :products do type [ProductType] resolve -> (shop, args, ctx) do shop.products end end
Product Load (1.0ms) SELECT "products".* FROM "products" WHERE "products"."shop_id" =
… Image Load (0.9ms) SELECT "images".* FROM "images" WHERE "images"."product_id" = … Image Load (0.2ms) SELECT "images".* FROM "images" WHERE "images"."product_id" = … Image Load (0.1ms) SELECT "images".* FROM "images" WHERE "images"."product_id" = …
Solution: Batching + Caching
field :image do type ImageType resolve -> (product, args, ctx)
do RecordLoader.for(Image).load(product.image_id) end end
HTTP Caching
Solution: Client Side Cache
Normalized Cache
Normalized Cache
query { shop { products { price } } }
query { shop { product(id: 1) { price } } }
{ root: { shop: { products: [ Link.new(1) ] }
}, 1: { price: 1000 } }
https://github.com/facebook/relay http://www.apollostack.com/
Security
Query Depth Timeouts Query Complexity
Future
Subscriptions
subscription { productInventorySubscribe { products { inventory } } }
Deferred Queries
query { shop { name description products { name price
} } }
query { shop { name description products { name price
} } }
query { shop { name description products @defer { name
price } } }
None
None
Thank you Marc-Andre Giroux @__xuorig__