• Docs
  • Transforms
  • Cache

Cache Transform

The cache transform allows you to easily apply caching over your data sources.

It allows you to configure custom invalidation rules (by TTL/mutation) and selective caching according to your needs.

💡

This transform is being applied globally because of the need to communicate with other GraphQL operations from your mesh.

To get started with this transform, install it:

yarn add @graphql-mesh/transform-cache
💡

GraphQL Mesh uses a default localforage cache (it is fallback to LRU cache in NodeJS), but you can replace it with any other key=>value cache mechanism. See cache section for more info. We'd recommend this transform be used on the root level, not the handler level. It might not work as expected if you use it on a handler level.

How to use?

Simple caching

To cache some of your queries, apply the following transform rule. The following example will cache all Query.* in your schema forever:

transforms:
  - cache:
      - field: Query.*

You can also apply it to a specific field or multiple fields:

transforms:
  - cache:
      - field: Query.users
  - cache:
      - field: Query.posts

The Cache Key

Each cache record is stored with a key. The default way of creating this key is to use the GraphQL type name, the GraphQL field name, and a hash of the args object. This is in order to make that we can distinct the cache key according to the data it's storing.

You can customize the cacheKey according to your needs, and you can use custom helpers to help you create those cache keys dynamically.

The following example creates a cacheKey by a GraphQL query argument called userId per day:

transforms:
  - cache:
      - field: Query.user
        cacheKey: user-{args.id}-{yyyy-mm-dd | date}

Cache Invalidation

TTL

Invalidation by TTL is the simplest way to deal with your cache. You can specify any time (in seconds) to keep your cache.

transforms:
  - cache:
      - field: Query.*
        invalidate:
          ttl: 3600 # 1 hour

Operation-based

GraphQL Mesh has a built-in operation-based caching solution.

You can cache data easily and invalidate it only when it changes by a mutation.

For example, given the following schema:

type Query {
  user(id: ID!): User!
}
 
type Mutation {
  updateUser(userIdToUpdate: ID!, setFields: UpdateUserInput!): User!
}
 
type User {
  id: ID!
  email: String!
  name: String
}
 
input UpdateUserInput {
  email: String
  name: String
}

You can set a simple caching based on a user id:

transforms:
  - cache:
      - field: Query.user
        cacheKey: user-{args.id}

And you can add operation-based invalidation, so when updateUser is done successfully, it will invalidate the matching cache record to make sure the data will be fetched next time from the remote source:

transforms:
  - cache:
      - field: Query.user
        cacheKey: user-{args.id}
        invalidate:
          effectingOperations:
            - operation: Mutation.updateUser
              matchKey: user-{args.userIdToUpdate}

This way, when someone uses updateUser with a specific user id, it will automatically update the data record and then invalidate the cache

Programmatic

The getBuiltMesh method of GraphQL Mesh artifacts returns the general key=>value cache it uses at the moment, so you can easily access it and invalidate records according to your needs:

const { getBuiltMesh } = require('./.mesh')
const { schema, execute, cache } = getBuiltMesh()
 
cache.delete(SOME_KEY)

Codesandbox Example

You can check the "Location Weather" example that uses OpenAPI handler with cache transform;

Config API Reference

  • field (type: String, required) - The type and field to apply cache to, you can use wild cards as well, for example: Query.*
  • cacheKey (type: String) - Cache key to use to store your resolvers responses. The default is: {typeName}-{fieldName}-{argsHash}-{fieldNamesHash}

Available variables:

  • {args.argName} - use resolver argument
  • {typeName} - use name of the type
  • {fieldName} - use name of the field
  • {argsHash} - a hash based on the 'args' object
  • {fieldNamesHash} - a hash based on the field names selected by the client
  • {info} - the GraphQLResolveInfo of the resolver

Available interpolations:

  • {format|date} - returns the current date with a specific format
  • invalidate (type: Object) - Invalidation rules:
    • effectingOperations (type: Array of Object, required) - Invalidate the cache when a specific operation is done without an error:
      • operation (type: String, required) - Path to the operation that could effect it. In a form: Mutation.something. Note that wildcard is not supported in this field.
      • matchKey (type: String) - Cache key to invalidate on successful resolver (no error), see cacheKey for list of available options in this field.
    • ttl (type: Int) - Specified in seconds, the time-to-live (TTL) value limits the lifespan
Last updated on July 27, 2022