Edge Caching

Edge caching is a performance optimization strategy implemented in your GraphQL API to cache responses in proximity to the end-users. This technique significantly cuts down overall latency, augmenting the speed of data delivery.

Caching is configured using the @cache directive.

Caching can be configured globally, by type, or field using the configurations below. This gives you an advanced tool for customizing caching behavior, enabling you to fine-tune the settings to optimally meet your project needs.

Global configuration applies caching to all types and fields that are returned by GraphQL queries. This is extremely powerful when used with API connectors.

extend schema @cache(rules: [{ types: ["Post", "User"] }]) {
  query: Query
}

In the example below we will cache the Post model and any of its fields for 60 seconds.

type Post @model @cache(maxAge: 60, staleWhileRevalidate: 60) {
  title: String!
  slug: String!
  content: String!
}

In the example below we will cache the Post model and any of its fields for 60 seconds, but only for 30 if the response contains the field content.

type Post @model @cache(maxAge: 60, staleWhileRevalidate: 60) {
  title: String!
  slug: String!
  content: String! @cache(maxAge: 30, staleWhileRevalidate: 60)
}

The configuration for caching rules are outlined below:

The types field is required for caching responses and allows targeting specific types.

It supports three formats: a single String for a single type, an array of String for multiple types, or a structured array of rules for targeting fields and types.

extend schema @cache(rules: [{ types: "Post" }]) {
  query: Query
}

Use the maxAge value to specify how long (in seconds) the cached entry is considered to be fresh.

extend schema @cache(rules: [{ maxAge: 60 }]) {
  query: Query
}

The lowest value for maxAge always wins for nested cache rules.

Use the staleWhileRevalidate value to specify how long (in seconds) the cached entry is considered to be stale.

extend schema @cache(rules: [{ maxAge: 30, staleWhileRevalidate: 60 }]) {
  query: Query
}

Cache entries transition through various states during their lifespan. The cache key is computed using the GraphQL query, variables, request authentication, and request domain.

The total time of a cache entry (TTL) is: maxAge + staleWhileRevalidate . After this TTL elapses, entries are evicted and deleted from cache.

The list below outlines the expected states visible in x-grafbase-cache response header:

x-grafbase-cache: MISS

No cache key found. Forwarding request to upstream for response retrieval and asynchronous cache put to minimize latency.

x-grafbase-cache: HIT

The cache contains a key that matches the incoming request. Clients will receive the response from the cache.

x-grafbase-cache: UPDATING

A matching key was found in the cache for the incoming request, but it has exceeded the maxAge limit. Clients will receive the cached response while we asynchronously refresh the entry.

x-grafbase-cache: STALE

The cache contains a key that matches the incoming request, but it has exceeded the maxAge limit and previous attempts to refresh it have failed.

You can also cache introspection queries by using the the following global configuration:

extend schema
  @cache(
    rules: [
      {
        maxAge: 60
        staleWhileRevalidate: 60
        types: [{ name: "Query", fields: ["__schema"] }]
      }
    ]
  ) {
  query: Query
}
Was this page helpful?