This past year, our team started using a GraphQL orchestration layer that connects various APIs with multiple front-end apps including iOS. It also handles caching and extracts some business logic out of our client apps. This helped us not only to be more consistent with the way we fetch data across apps, but also improved developer happiness and even bridged teams by having our web and iOS developers work with the same API layer. This got me thinking what other problems GraphQL could solve at Artsy.
I work on the Publishing Team at Artsy, and we've recently been focused on page speed as a KPI. With so many ways of measuring speed, it's a daunting task but for this post, I'll focus on the way we handled things on the server-side and how integrating GraphQL on our API improved page speed.
Prior to GraphQL
In our publishing CMS called Positron, we serve a separate API, database, and front-end from the rest of the Artsy stack. We're also responsible for the delivery and presentation of the content itself. Over the past year we've focused a lot on how the content appears, and now we've opened up time to focus on speed since in the land of content, every second counts.
Before we went ahead with adding a GraphQL-based endpoint to Positron, I spent about a week and refactoring our current codebase. We refactored our router code to make less fetches, made better use of caching, and moved some below-the-fold rendering into the client side. These are important steps towards a faster page, but it doesn't push our technology in a direction that lets us reimagine things.
We split the speed problem in two:
Server Response Time (server-side) and
Document Interactive Time
(client-side). We currently use Google Analytics to track these
metrics. There are some inaccuracies with GA such as
small sampling, geographic noise (countries with different download speeds), and timeouts being counted as zero,
but for our initial testing this will suffice for relative measuring.
Enter GraphQL and JoiQL
Our very own Craig Spaeth recently started working on a project called Mural. It's a framework for React and GraphQL. One library that came out of this project is called JoiQL. It's a The main purpose of JoiQL is to convert Joi schemas into GraphQL schemas.
We already use Joi in Positron so creating a GraphQL-based endpoint was trivial with JoiQL. Note that while JoiQL is currently used in production, it's still a beta project! Below is an example of how the JoiQL setup works.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
You can see how simple it becomes to convert apps that already use Joi with JoiQL. Joi provides a nice API for building GraphQL schemas with minimal boilerplate and we also get a nice Koa 2 style middleware pattern that lets us hook into a downstream/upstream flow. This downstream/upstream flow could be useful later on if we were to get really granular with measuring speed. For instance, if we decide to track the speed of the whole lifecycle of a request, we could do something like this:
1 2 3 4 5 6 7 8 9 10
The two features of GraphQL that have been helpful for reducing page speed are:
- Reduced payload because you only request the data you need
- Multiple fetches can be coalesced into a single request
Reduced payload turned out to be one of the biggest factors in reducing speed. Just after October 27 we switched over to using GraphQL on our mobile articles landing page.