What is GraphQL?
GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. By running a GraphQL server (e.g. Apollo GraphQL), your existing applications can send parameterised requests and get back JSON responses.
What is it good for?
Is GraphQL The answer to all of life’s problems? Maaaaaaybe? But it isn’t a database or a web server, the two things its most often confused for. Let’s dive in.
GraphQL is a communication standard. Its goal is to let you request all the data you need with a single fairly compact request. It was born as an attempt to improve on REST APIs for populating web pages with data. The classic conundrum looks like this:
WEBPAGE: When Bob comments on a photo, I want to show a tooltip with profile pics of Alice and Bob’s top 5 mutual friends.
APP: okay, here’s Bob’s ‘user’ record
WEBPAGE: this has all his friend’s IDs, I need their mutual friends.
APP: hey good news I built an endpoint that takes two users IDs and returns their mutual friends
WEBPAGE: Great!
APP: they have 137 mutual friends
WEBPAGE: geez I want the top 5 by date, but… okay, now can I get their profile pictures
APP: sure here’s the first friend’s ‘user’ record
WEBPAGE: I need-
APP: here’s the second friend complete ‘user’ record
WEBPAGE: you don’t just have the photos?
APP: nope! Here’s the third friend’s ‘user’ record. Geez this is taking a while, huh? SOMEone’s on 3g, amirite?
-fin-
What’s wrong with this picture? In general two things:
- Overfetching: while most REST API’s will have a way to ask for a ‘top 5’, there’s usually no way to ask for some information. We only wanted Bob’s mutual friends, and then after that we only wanted the mutuals photos not their full profiles
- Multiple round trips: the very last request, for all 5 mutual friends' user profiles could be done in parallel, but all the steps before that would have to happen synchronously, waiting for a full reply before the next step could happen. If you think this isn’t a problem, you need to be a bit better informed about the public’s level of broadband access
In this scenario, no ‘bad engineering’ happened with this REST API, in fact the work’s been done to return filtered and scoped lists for some requests! But it is true that the front-end page team doesn’t have access to set up the exact API endpoints they need. This is an important point and I want to emphasize it a bit.
If you have full access to alter your REST API, you don’t need GraphQL
If your pal, the backend developer, is working with you to set up this feature, they can absolutely set up user/views/top5mutualpics and give you just the data you need, but the trouble starts as your operation grows and features on the front end need to be delivered without API changes. This probably means your org is growing, your user base is growing, and that you expect the frontend to grow and change without updates to your API, so it’s probably a good thing!
Benefits of GraphQL
GraphQL allows you to request data to the depth and in the shape that you need. It also implicitly lets you scope your request to get only the fields you need
{
hero {
name
}
}
The response we get back will be JSON in this shape:
{
"data": {
"hero": {
"name": "R2-D2"
}
}
}
This example is done on the lovely Star Wars API (SWAPI) endpoint, check out its GraphQL interface here
So there’s no need to create separate /profile /profile_posts and /profile_vitals endpoints to get more focused versions of the data. The goal here is to have GraphQL "wrap around" your existing REST API end points and provide a new, unified interface that lets me query all the things.
Tips for the beginner writing GraphQL queries
I saw an amazing talk from Sean Grove of One Graph who works on maintaining GraphiQL, the rad graphical explorer for GraphQL. He talked about adding automations to GraphQL to let it point new query writers in the direction of more efficient coding of GraphQL queries. The query language is supposed to be easy, so these points shouldn’t add significantly to the weight of writing new queries.
Optimize with variables
GraphQ: lets you parameterise queries. Here we are making a query asking for a particular hero that matches the film name "NEW HOPE" and the names of their friends:
hero(“NEW HOPE”) {
name
friends {
name
}
}
This looks pretty good but updating this query will require some string manipulation by our GraphQL client (e.g. the React web app that will be asking for data). Also, later queries with different parameters will not benefit from any caching, since the GraphQL server will see it as a whole new query. So it’s better to add a variable to a query, then re-use the same query over and over:
query HeroNameAndFriends($episode: Episode) {
hero(episode: $episode) {
name
friends {
name
}
}
}
This example and others in this article are cribbed from the GraphQL learn pages
Now we can update the episode variable and re-run the same query, and it’ll impact the client less AND return faster.
Set defaults for your variables
If you love the other devs on yourself or even future you, you’ll set defaults on your variables to make sure each query succeeds
query HeroNameAndFriends($episode: Episode = JEDI) {
hero(episode: $episode) {
name
friends {
name
}
}
}
Later you can re-use this query as
HeroNameAndFriends('EMPIRE')
and benefit from caching!
Write more DRY (‘don’t repeat yourself’) queries with fragments
It’s an amazing feature that you get to specify exactly the fields that you want to get back from a GraphQL query, after a while this can get… kinda tedious:
hero(episode: $episode) {
name
height
weight
pets {
name
height
weight
}
friends {
name
height
weight
}
}
If this was a query we might be asking for photos, IDs, friends’ IDs, over and over again as the query has more clauses. Surely there’s a way to ask for:
`name`
`height`
`weight`
All at once? Yup!
Define a fragment like so:
fragment criticalInfo on Character {
name
height
weight
}
Note that Character is just a label I’m using in this example, i.e. a character in a story
Now our query is much more compact:
hero(episode: $episode) {
...criticalInfo
pets {
...criticalInfo
}
friends {
...criticalInfo
}
}
Ready to dive in and go further?
My next article will cover how to host your first GraphQL server on Heroku, and after that how to build your first service architecture.
Your next step if all this is interesting to you should be to get a full series on GraphQL queries right from the GraphQL team on their learn page.
If you want to really learn GraphQL, I cannot recommend highly enough “Learning GraphQL” by Alex Banks and Eve Porcello.
This and the several articles that will follow it brought to you by my favorite train read the last few weeks.