# Execution Caching

The @cache directive enables to cache the result of a heavy-to-compute operation. The first time the field is resolved, the @cache directive will save the value in disk or memory (Redis, Memcached), either with an expiry date or not, and from then on whenever querying this field the cached value will be retrieved and the operation will not be performed.

For instance, this query executes the @translate directive, which does a single connection to the Google Translate API and performs the translation of the posts' titles:

query {
  posts(limit:3) {
    id
    title @translate(from:"en", to:"es")
  }
}

Assuming this is an expensive call, we can cache the field's value after the first response. This query achieves that through the @cache directive, passing a time expiration of 10 seconds (not passing this value, the cache does not expire):

query {
  posts(limit:3) {
    id
    title @translate(from:"en", to:"es") @cache(time:10)
  }
}

TIP

Directives in GraphQL are applied in order, so the following queries are different:

  • title @translate @cache
  • title @cache @translate

In the 1st case, it executes @translate and then @cache, so the translation is being cached; in the 2 case, it executes @cache and then @translate, so the caching only stores the value of the title field and not its translation.

The first time we execute the query, we obtain this response:

1st execution of query with @cache directive

The 2nd time, executing the same query within 10 seconds, we obtain the same response, but a log also informs us that the value is coming from the cache:

2nd execution of query with @cache directive

Tip: How to show logs in the response

Logs are retrieved by passing parameter show_logs=true to the GraphiQL client, which sets parameter actions[]=show-logs to the GraphQL endpoint /api/graphql/

Please notice how the log indicates which are the items that have been cached. If we increase field post's limit to 6, and run again within 10 seconds, the already-cached 3 items will be retrieved from the cache, and the other 3, which had not been cached yet, will be retrieved fresh through Google Translate:

3rd execution of query with @cache directive

If we run it again, now all 6 items will be cached:

4th execution of query with @cache directive

# Configuration

# Caching adapter

GraphQL by PoP uses Symfony's Cache Component for caching.

By default it stores the cache in the file system, through the Filesystem Cache Adapter, as configured in file services.yaml from package Component Model:

services:
    persistent_cache_item_pool:
        class: \Symfony\Component\Cache\Adapter\FilesystemAdapter
        public: true

Defining service persistent_cache_item_pool on another package will override the default adapter. For instance, for improving performance, we can store the cache in memory using Redis (through this adapter) or Memcached (through this adapter).

The full list of adapters is here.

Last Updated: 1/19/2021, 12:16:46 AM