GraphQL caching
Magento can cache pages rendered from the results of certain GraphQL queries with full-page caching. Full-page caching improves response time and reduces the load on the server. Without caching, each page might need to run blocks of code and retrieve large amounts of information from the database. Only queries submitted with an HTTP GET operation can be cached. POST queries cannot be cached.
Cached and uncached queries
The definitions for some queries include cache tags. Full page caching uses these tags to keep track of cached content. They also allow public content to be invalidated. Private content invalidation is handled on the client side.
GraphQL allows you to make multiple queries in a single call. If you specify any query that Magento does not cache, Magento bypasses the cache for all queries in the call.
Magento caches the following queries:
category
(deprecated)categoryList
cmsBlocks
cmsPage
products
urlResolver
Magento explicitly disallows caching the following queries.
cart
country
countries
currency
customAttributeMetadata
customer
customerDownloadableProducts
customerOrders
customerPaymentTokens
storeConfig
wishlist
Define the GraphQL schema for a module describes the syntax of a valid query.
Caching with Varnish
We recommend setting up Varnish as a reverse proxy to serve the full page cache in a production environment. See Configure and use Varnish for more information.
As of Magento 2.3.2, Magento supports GraphQL caching with Varnish. If you have upgraded from a previous version, you can enable GraphQL caching by generating a new template file, or by editing the default.vcl
file on your system to match the current default template for your version of Varnish.
If you choose to edit an existing default.vcl
file, update the vcl_hash
subroutine to check whether the request URL contains graphql
, as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sub vcl_hash {
if (req.http.cookie ~ "X-Magento-Vary=") {
hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
}
# For multi site configurations to not cache each other's content
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
if (req.url ~ "/graphql") {
call process_graphql_headers;
}
# To make sure http users don't see ssl warning
if (req.http./* */) {
hash_data(req.http./* */);
}
}
Then add the process_graphql_headers
subroutine:
1
2
3
4
5
6
7
8
sub process_graphql_headers {
if (req.http.Store) {
hash_data(req.http.Store);
}
if (req.http.Content-Currency) {
hash_data(req.http.Content-Currency);
}
}
Query results should not be cached for logged in customers, because it cannot be guaranteed that these results are applicable to all customers. For example, you can create multiple customer groups and set up different product prices for each group. Caching results like these might cause customers to see the prices of another customer group.
To prevent customers from seeing the incorrect data from cached results, add the following to your .vcl
file in the vcl_recv
subroutine before the return (hash):
1
2
3
4
# Authenticated GraphQL requests should not be cached by default
if (req.url ~ "/graphql" && req.http.Authorization ~ "^Bearer") {
return (pass);
}
This statement prevents any query with an authorization token from being cached.
Configure Varnish and your web server further describes how to configure the default.vcl
file.
Caching with Fastly
To cache GraphQL query results on Adobe Commerce on cloud infrastructure, the Cloud project must be running Fastly CDN module for Magento 2 version 1.2.118 or later.
To enable GraphQL caching on Fastly:
- Upgrade the Fastly CDN Module for Magento 2.x to version 1.2.118 or later.
- Upload the updated VCL code to the Fastly servers.
Set up Fastly describes how to perform both of these tasks.
By default, the Fastly module for Magento provides the following VCL configuration for GraphQL caching:
1
2
if (req.request == "GET" && req.url.path ~ "/graphql" && req.url.qs ~ "query=") {
....
Fastly will only cache GET requests that contain a query parameter in the request URL.
Example
1
2
http://example.com/graphql?query={ products(filter: {sku: {eq: "Test"}}) { items { name } } }&variables={}
....
If you call GraphQL queries in the query body rather than the URL (for example, as --data-raw '{"query" .... }'
), the request is not cached.
X-Magento-Vary
The X-Magento-Vary
cache cookie is not supported for GraphQL. The Store
and Content-Currency
headers, along with the content language (which is deduced) determine the context.
Response headers
In developer mode, Magento returns several headers that could be useful for debugging caching problems. These headers are not specific to GraphQL.
Header | Description |
---|---|
X-Magento-Cache-Debug |
HIT (the page was loaded from cache) or MISS (the page was not loaded from cache. |
X-Magento-Tags |
A list of cache tags that correspond to the catalog, category, or CMS items returned in the query. Magento caches these items. |
Cache invalidation
Magento invalidates the cache when any of the following events occur:
- When a change occurs to a specific entity or entities in aggregate. An increase in a product’s price is a direct and obvious change. Applying a new tax class tax to products changes a set of products in aggregate.
- When system configuration changes
- When an administrator flushes or disables the cache from the Admin or with the
bin/magento cache
command