Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Designing and implementing GraphQL API
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Mariusz Gil
May 31, 2019
Programming
120
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Designing and implementing GraphQL API
Mariusz Gil
May 31, 2019
More Decks by Mariusz Gil
See All by Mariusz Gil
Aspect Oriented Programming
mariuszgil
1
350
Discovering unknown with EventStorming ConFoo
mariuszgil
0
330
Game of Developer Life... Deconstructed
mariuszgil
1
200
Back to forgotten roots
mariuszgil
1
450
Go micro with microservices
mariuszgil
5
720
Machine Learning for the rescue
mariuszgil
0
470
Discovering graph structures
mariuszgil
3
570
Introduction to Aerospike with PHP
mariuszgil
8
880
Processing events at scale
mariuszgil
2
410
Other Decks in Programming
See All in Programming
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
5
3.3k
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
140
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
190
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
170
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
160
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
0
1.5k
SREの越境 / SRE Collaboration
y0hgi
2
240
Family mrubyの進捗
kishima
1
130
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
6
2.3k
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
180
Are APIs Still Relevant in the AI Era?
soyuka
0
260
WebAssembly in Android Apps 〜 WASMはJNIの夢を見るか
keiji
1
110
Featured
See All Featured
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Product Roadmaps are Hard
iamctodd
55
13k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
730
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Building AI with AI
inesmontani
PRO
1
1.2k
Writing Fast Ruby
sferik
630
63k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Utilizing Notion as your number one productivity tool
mfonobong
4
590
Transcript
DEsigning and implementing Mariusz Gil @mariuszgil GRAPHQL API
None
None
None
None
None
Modeling database theory
Searching data with elastic search
storing data with mYsql 8
Now it is time for… accessing our data from app
Let’s start in 2000
None
All is resource based ]
All is resource based With extra constraints ]
/tweets Resource / collection (or store) archetype
/tweets/123 Resource / document archetype
/tweets/123/media Resource / (embedded) collection archetype
/tweets/123/media/123 Resource / document archetype, inside (embedded) collection
/tweets/123/block Resource / controller archetype
/tweets Resource GET PUT POST PATCH DELETE http method
/tweets Resource GET PUT POST PATCH DELETE http method READ
REPLACE CREATE MODIFY DELETE Action / crUD-style + =
https://nordicapis.com/what-is-the-richardson-maturity-model/
None
Main REST API pros Easy to understand Easy to document
Easy to use Easy to implement Easy to scale Resources are disconnected from representations
Main REST API cons Communication ping-pong Network heavy Time consuming
… Communication ping-pong Network heavy Time consuming
Let’s talk about other options ]
None
Graphql is query language for api With server runtime for
processing queries Using defined type system
Type system ]
type Tweet { id: ID! created_at: String! text: String! }
type User { id: ID! screen_name: String! name: String! profile_image_url: String created_at: String! }
type Tweet { id: ID! created_at: String! text: String! user:
User } type User { id: ID! screen_name: String! name: String! profile_image_url: String created_at: String! }
type Tweet { id: ID! created_at: String! text: String! user:
User } type User { id: ID! screen_name: String! name: String! profile_image_url: String created_at: String! tweets: [Tweet] }
type Tweet { id: ID! created_at: String! text: String! user:
User } type User { id: ID! screen_name: String! name: String! profile_image_url: String created_at: String! tweets: [Tweet] tweets_count: Int }
type Tweet { id: ID! created_at: String! text: String! user:
User } type User { id: ID! screen_name: String! name: String! profile_image_url: String created_at: String! tweets: [Tweet] tweets_count: Int } type Retweet { id: ID! created_at: String! in_reply_to_tweet_id: String! in_reply_to_user_id: String! retweeted_status: Tweet! user: User }
type Tweet { id: ID! created_at: String! text: String! user:
User retweets: [Retweet] retweet_count: Int } type User { id: ID! screen_name: String! name: String! profile_image_url: String created_at: String! tweets: [Tweet] tweets_count: Int } type Retweet { id: ID! created_at: String! in_reply_to_tweet_id: String! in_reply_to_user_id: String! retweeted_status: Tweet! user: User }
type Tweet { id: ID! created_at: String! text: String! user:
User retweets: [Retweet] retweet_count: Int } enum SearchResponse { mixed recent popular } type User { id: ID! screen_name: String! name: String! profile_image_url: String created_at: String! tweets: [Tweet] tweets_count: Int } type Retweet { id: ID! created_at: String! in_reply_to_tweet_id: String! in_reply_to_user_id: String! retweeted_status: Tweet! user: User }
interface Tweet { id: ID! created_at: String! text: String! user:
User retweets: [Retweet] retweet_count: Int }
type TextTweet implements Tweet { id: ID! created_at: String! text:
String! user: User retweets: [Retweet] retweet_count: Int } type MediaTweet implements Tweet { id: ID! created_at: String! text: String! user: User media: [TweetImage] retweets: [Retweet] retweet_count: Int } interface Tweet { id: ID! created_at: String! text: String! user: User retweets: [Retweet] retweet_count: Int }
Communication ]
req resp req resp req resp CLIENT SERVER REST
WHAT YOU ASK IS WHAT YOU GET
req resp CLIENT SERVER GRAPHQL
req resp CLIENT SERVER Reads writes /graphql?q=…
{ twitter { tweet(id: "1134427651672875008") { text } } }
{ "data": { "twitter": { "tweet": { "text": "IT'S @daycamp4devs DAY! :) \\o/ \\o/ \\o/ \\o/ \\o/ https://t.co/RrTFHQKUNt" } } } } REQUEST RESPONSE
{ twitter { tweet(id: "1134427651672875008") { text, created_at } }
} { "data": { "twitter": { "tweet": { "text": "IT'S @daycamp4devs DAY! :) \\o/ \\o/ \\o/ \\o/ \\o/ https://t.co/RrTFHQKUNt” "created_at": "Fri May 31 11:53:23 +0000 2019” } } } } REQUEST RESPONSE
{ twitter { tweet(id: "1134427651672875008") { text, created_at, user }
} } WRONG REQUEST! REQUEST RESPONSE
{ twitter { tweet(id: "1134427651672875008") { text, created_at, user {
screen_name } } } } { "data": { "twitter": { "tweet": { "text": "IT'S @daycamp4devs DAY! :) \\o/ \\o/ \\o/ \\o/ \\o/ https://t.co/RrTFHQKUNt”, "created_at": "Fri May 31 11:53:23 +0000 2019”, "user": { "screen_name": "CalEvans" } } } } } REQUEST RESPONSE
Let see it in action Almost live ;)
None
Query execution
{ twitter { tweet(id: "1134427651672875008") { text, created_at } }
} { "data": { "twitter": { "tweet": { "text": "IT'S @daycamp4devs DAY! :) \\o/ \\o/ \\o/ \\o/ \\o/ https://t.co/RrTFHQKUNt” "created_at": "Fri May 31 11:53:23 +0000 2019” } } } } REQUEST RESPONSE
import { GraphQLSchema, GraphQLObjectType, GraphQLID, GraphQLString, GraphQLNonNull, GraphQLInt, GraphQLList, GraphQLScalarType,
GraphQLEnumType } from "graphql"; DATA DEFINITION
let TweetType = new GraphQLObjectType({ name : 'Tweet', description :
'A tweet object', fields : () => ({ id : { type: GraphQLID }, created_at : { type: GraphQLString }, text : { type: GraphQLString }, retweet_count : { type: GraphQLInt }, }) }); DATA DEFINITION
let twitterType = new GraphQLObjectType({ name : 'TwitterAPI', description :
'The Twitter API', fields : { tweet: { type : TweetType, args : { id : { type : new GraphQLNonNull(GraphQLString), description : 'Unique ID of tweet' } } } } }); export const QueryObjectType = twitterType; DATA DEFINITION
let twitterType = new GraphQLObjectType({ name : 'TwitterAPI', description :
'The Twitter API', fields : { tweet: { type : TweetType, args : { id : { type : new GraphQLNonNull(GraphQLString), description : 'Unique ID of tweet' } }, // RESOLVER resolve: (_, { id: tweetId }) => YOUR DATA ACCESS CODE GOES HERE! } } }); export const QueryObjectType = twitterType DATA RESOLVER DEFINITION
let twitterType = new GraphQLObjectType({ name : 'TwitterAPI', description :
'The Twitter API', fields : { tweet: { type : TweetType, args : { id : { type : new GraphQLNonNull(GraphQLString), description : 'Unique ID of tweet' } }, // RESOLVER resolve: (_, { id: tweetId }) => twitter.getTweet(tweetId) } } }); export const QueryObjectType = twitterType; DATA RESOLVER DEFINITION
let TweetType = new GraphQLObjectType({ name : 'Tweet', description :
'A tweet object', fields : () => ({ id : { type: GraphQLID }, created_at : { type: GraphQLString }, text : { type: GraphQLString }, retweet_count : { type: GraphQLInt }, }) }); DATA DEFINITION
let TweetType = new GraphQLObjectType({ name : 'Tweet', description :
'A tweet object', fields : () => ({ id : { type: GraphQLID }, created_at : { type: GraphQLString }, text : { type: GraphQLString }, retweet_count : { type: GraphQLInt }, retweets : { type : new GraphQLList(RetweetType), description : 'Get a list of retweets', args : { limit: { type : GraphQLInt, defaultValue : 5 } }, // RESOLVER resolve: ({ id_str: tweetId }, { limit }) => YOUR DATA ACCESS CODE GOES HERE! } }) }); DATA RESOLVER DEFINITION
{ twitter { tweet(id: "1134427651672875008") { text, created_at, user {
screen_name, tweets(limit: 2) { retweets(limit: 2) { user { name } } } } } } } { "data": { "twitter": { "tweet": { "text": "IT'S @daycamp4devs DAY! :) \\o/ \\o/ \\o/ \\o/ \\o/ https://t.co/RrTFHQKUNt”, "created_at": "Fri May 31 11:53:23 +0000 2019”, "user": { "screen_name": "CalEvans", "tweets": [ { "retweets": [ { "user": { "name": "Eric Hogue" } }, { „user": { "name": "Cristiano D. Silva" } } ] }, { "retweets": [] } ] } } } } } REQUEST RESPONSE
Execution performance
req resp CLIENT SERVER /graphql?q=… GRAPHQL
req resp CLIENT SERVER GRAPHQL DATA STORAGE 1 REQUEST N+M
QUERIES? /graphql?q=…
Cache and batch your data, Even in request scope
None
var DataLoader = require('dataloader') var tweetLoader = new DataLoader(keys =>
batchedTweetKeys(tweetKeys)); var userLoader = new DataLoader(keys => batchedUserKeys(usersKeys)); tweetLoader.load(tweetId) .then(user => userLoader.load(user.id) .then(retweeted_to => tweetLoader.load(retweeted_to.id) DATALOADER DEFINITION
let TweetType = new GraphQLObjectType({ name : 'Tweet', description :
'A tweet object', fields : () => ({ id : { type: GraphQLID }, created_at : { type: GraphQLString }, text : { type: GraphQLString }, retweet_count : { type: GraphQLInt }, retweets : { type : new GraphQLList(RetweetType), description : 'Get a list of retweets', args : { limit: { type : GraphQLInt, defaultValue : 5 } }, resolve: ({ id_str: tweetId }, { limit }) => dbTeetLoader.load([ 'SELECT tweetId FROM retweets WHERE originalTweetId=? LIMIT ?', tweetId, limit ]).then(rows => rows.map(row => tweetLoader.load(row.tweetId))) } }) }); DATALOADER DEFINITION
Schema synchronization
Other use cases? ]
https://labs.getninjas.com.br/sharing-data-in-a-microservices-architecture-using-graphql
Kubernetes API gateway GRAPHQL server on top of gloo and
envoy
$> sqoopctl install kube SAMPLE CONFIGURATION
$> sqoopctl install kube $> kubectl apply -f PATH_TO_CONFIG/tweets.yaml SAMPLE
CONFIGURATION
$> sqoopctl install kube $> kubectl apply -f PATH_TO_CONFIG/tweets.yaml $>
glooctl get upstream +--------------------------------+------------+----------+-------------+ | NAME | TYPE | STATUS | FUNCTION | +--------------------------------+------------+----------+-------------+ | gloo-tweets-8080 | kubernetes | Accepted | getTweet | +--------------------------------+------------+----------+-------------+ SAMPLE CONFIGURATION
$> kubectl get upstreams -n gloo-tweets-8080 -o yaml apiVersion: gloo.solo.io/v1
kind: Upstream metadata: // TRUNCATED spec: upstreamSpec: kube: selector: app: tweets serviceName: tweets serviceNamespace: gloo-system servicePort: 8080 serviceSpec: rest: transformations: getTweet: body: {} headers: :method: text: GET :path: text: /api/tweets/{{ default(id, "") }} content-length: text: "0" content-type: {} transfer-encoding: {} SAMPLE CONFIGURATION
$> sqoopctl schemat create tweets -f tweets.graphql $> sqoopctl resolvermap
register -u default-tweets-8080 -s tweets getTweet Query tweet SAMPLE CONFIGURATION
Where to look for more? ]
None
None
None
None
None
thanks @mariuszgil