Using Stellate to Make WPGraphQL MUCH Faster

June 12, 2023

Featured

The Problem

Nearly everything about GraphQL is exciting to frontend developers. We get to tell our APIs exactly what we want, we get a JSON object with that data, and then we can use it exactly the way that we want to. What's even better than this fine grain control? It's wicked fast. Or at least, it should be.

Enter WPGraphQL. Since we've been doing quite a bit of work at Tattoo Projects with headless WordPress and Sveltekit we have been leaning on this implementation of GraphQL quite a bit to interact with the WP API. However, we have been running into serious speed issues. These issues stem from a myriad of problems. It's issues with WP itself as a technology, it's issues with the implementation of WPGraphQL, and it was issues with the way we wrote our queries in the first place.

We were seeing response times of nearly a second at times for a simple blog post. This is obviously unacceptable, and we needed to make things a lot faster.

The Solution

After fixing all my issues with the requests themselves, such as streamlining multiple queries into one to reduce round trip time for all the data needed, I began scouring the internet for solutions. The obvious answer: caching. Okay, sure, caching data on the edge would help, but isn't there already a WPGraphQL official plugin that does that in the form of Smart Cache?

Smart cache doesn't even get close to touching what I found Stellate was capable of doing. I fired up a free account, followed the instructions for installing the plugin in WP, and retested my response times. Aaaaaand: nothing.

How to Properly Configure Stellate for WPGraphQL

Stellate, to their credit, is a great tool. But their docs were somewhat lacking. I found that there were several other steps to get caching and metrics working well. I'll document them here. Again, if you haven't installed Stellate, their docs go over that part quite well, read them here.

Step 1:

First thing you may notice after getting Stellate set up is you'll be getting quite a few errors in the console. That's because Stellate attempts to use Schema Introspection to determine types to cache. However, public introspection is disabled by default on WPGraphQL. If you are comfortable enabling public introspection, the errors will go away. Here is how:

WPgQLIntro.png

You can find this under settings in WPGraphQL menu on the WordPress dashboard. This will help to decrease errors in the Stellate console, but we aren't going any faster on our site. Let's fix that.

Step 2:

To make sure our cache is actually working, we need to add caching rules for our types within our schema. I have a query called "getResources" that pull both the "post" type and the "CaseStudy" type. Note that the types are the singular form, not the plural form. Let's add the caching rules for these types to our config block:

import { Config } from 'stellate'

const config: Config = {
  config: {
    name: 'YOUR_SERVICE_HERE',
    originUrl: 'YOUR_ENDPOINT_HERE',
    cacheIntrospection: true,
    enablePlayground: true,
    devPortal: {
      enabled: true,
      auth: false,
    },
    rootTypeNames: {
      query: 'RootQuery',
      mutation: 'RootMutation',
    },
    rules: [
      {
        types: ['Post'],
        maxAge: 900,
        swr: 900,
        description: 'Cache Posts',
      },
       {
        types: ['CaseStudy'],
        maxAge: 900,
        swr: 900,
        description: 'Cache Case Studies',
      },
    ],
  },
}
export default config

Here you can see that I create two objects under the rules, one for "Post" and one for "CaseStudy". Once I added these rules, these queries will trigger a couple misses, and then the cache will start hitting. I saw a 600% increase in speed, from 489MS to 83MS. Some other queries for these types were even faster.

If you don't know which types you need to cache, you can go to the metrics tab and click on any cache "PASS". It will show the types that are being fetched, and you can then add rules for those types.

Caveats

There is one caveat with this approach in that Stellate is a paid, hosted service. If your client has data retention policies, or plans on having over 1 million requests, it is likely that you'll have to discuss Stellate with them to make sure they are on board with:

  • Data persistence in a secondary service.
  • Additional costs associated with the Stellate paid plans.

Beyond these, I don't see a disadvantage to using the Stellate caching service when working with WPGraphQL, or any slower implementation of gQL. Happy hacking!