Cache Rules

The Stellate Edge Cache gives you fine-grained per-type or even per-field control over your cache behavior for every single query that is sent through your service with cache rules.

GraphQL edge cache configuration basics

A basic rule to cache all queries that contain any User could look like this:

import { Config } from 'stellate'

const config: Config = {
  config: {
    rules: [
      {
        types: ['User'],
        maxAge: 900,
        swr: 900,
        scope: 'AUTHENTICATED',
        description: 'Cache Users',
      },
    ],
  },
}
export default config

A rule applies to all queries that contain the rule's types or fields. If multiple rules apply to the same query, Stellate will use the minimum maxAge, the minimum swr, and combine all scopes to cache the query result.

types (required)

The rule will apply its cache configuration to any query that contains the types or fields mentioned in the types property.

You can target both types as well as specific fields of types:

import { Config } from 'stellate'

const config: Config = {
  config: {
    rules: [
      {
        types: {
          // This rule will apply to any query that contains any User
          User: true,

          // This rule will apply to any query that contains Post.comments
          Post: ['comments'],

          // This rule will apply to any "{ drafts }" query
          // (assuming the "Query" type is the root schema query type)
          Query: ['drafts'],
        },
      },
    ],
  },
}
export default config

maxAge (seconds, optional)

The maxAge parameter configures how long query results that match the rule types should be cached, in seconds. If multiple rules apply to the same query, the minimum maxAge will be used for the entire query result.

swr (stale-while-revalidate, seconds, optional)

The "swr" (stale-while-revalidate) property configures how long stale query results that match the rule types should be served while fresh data is already being fetched in the background.

For example, if you set the maxAge of a query to 60s and swr to 300s, depending on when new requests come in the following actions are taken:

  1. Within the first 60 seconds, the cached result will be returned from our edge locations.
  2. From 60s to 360s we will pass on the first request to your backend service, but continue to serve the cached (but stale) results for other identical requests. As soon as we get an updated response from your backend service we will update the cached data.
  3. Any requests coming in later than 360s will get passed on to your backend service. The first response will re-populate the cache.

We would recommend always configuring stale-while-revalidate, as well as keeping the swr limits fairly high. Your users will get a very quick response to their request, while we load potentially updated data in the background and update the cache.

If you want to read more about this topic, please see Keeping things fresh with stale-while-revalidate by Jeff Posnick.

scope (string, optional)

Which scope to apply to query results that match the rule types. See the documentation on Scopes for more information on setting up scopes.

description (string, optional)

Description of the purpose of the rule in plain English.

FAQ

How do I cache every GraphQL query?

To apply a rule to everything, target the root Query type. This might look like the following example, if you did not rename that type.

import { Config } from 'stellate'

const config: Config = {
  config: {
    rules: [
      {
        types: ['Query'],
        maxAge: 900,
        swr: 900,
        description: 'Cache everything',
      },
    ],
  },
}
export default config

How to not cache a type

If you want to make sure a specific type (or field) is not getting cached at all, you can configure a new cache rule targeting that type and setting the maxAge and swr fields to 0.

import { Config } from 'stellate'

const config: Config = {
  config: {
    rules: [
      {
        types: ['User'],
        maxAge: 0,
        swr: 0,
        description: 'Do not cache the `User` type',
      },
    ],
  },
}
export default config

What happens when multiple rules apply to the same GraphQL query?

Stellate will use the minimum maxAge, and the minimum swr and combine all scopes to cache the query result.

For example, imagine you have these two rules defined:

import { Config } from 'stellate'

const config: Config = {
  config: {
    rules: [
      {
        types: ['Posts'],
        maxAge: 900,
        swr: 900,
        description: 'Cache Posts publicly',
      },
      {
        types: ['User'],
        maxAge: 450,
        swr: 1000,
        scope: 'AUTHENTICATED',
        description: 'Cache User data privately',
      },
    ],
  },
}
export default config

And send a query that contains a User and a Post, which means both rules apply:

{
  user(id: "...") {
    id
    posts(first: 10) {
      id
    }
  }
}

Then the query result would be cached with a 450s maxAge (the minimum of both rules), a 900s swr (the minimum of both rules) as well as with a scope of AUTHENTICATED (the combination of all the scopes applied via the rules).