Edit in GitHubLog an issue

Public content

By default, all pages in Adobe Commerce and Magento Open Source are cacheable, but you can disable caching if necessary (e.g., payment method return page, debug page, or AJAX data source).

Caching#

If you need to refresh data every second consider using a cache. Requesting content from the cache is faster than generating it for every request.

Only GET and HEAD methods are cacheable.

Disable or enable caching#

Add a cacheable="false" attribute to any block in your layout to disable caching:

Copied to your clipboard
<block class="Magento\Paypal\Block\Payflow\Link\Iframe" template="payflowlink/redirect.phtml" cacheable="false"/>

The application disables page caching if at least one non-cacheable block is present in the layout.

You can also disable caching with HTTP headers. Use a controller to return an object that contains methods for manipulating the cache.

Define caching behavior#

You can use the Admin to define caching policies or you can define them programmatically in a controller:

Example

Copied to your clipboard
1<?php
2/**
3 * Copyright © Magento, Inc. All rights reserved.
4 * See COPYING.txt for license details.
5 */
6
7use Magento\Framework\App\Action\Action;
8use Magento\Framework\App\Action\Context;
9use Magento\Framework\View\Result\PageFactory;
10
11class DynamicController extends Action
12{
13 protected $pageFactory;
14
15 public function __construct(
16 Context $context,
17 PageFactory $resultPageFactory
18 ) {
19 parent::__construct($context);
20 $this->pageFactory = $resultPageFactory;
21 }
22
23 /**
24 * This action render random number for each request
25 */
26 public function execute()
27 {
28 $page = $this->pageFactory->create();
29 //We are using HTTP headers to control various page caches (varnish, fastly, built-in php cache)
30 $page->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0', true);
31
32 return $page;
33 }
34}

Configure page variations#

Most caching servers and proxies use a URL as a key for cache records. However, Adobe Commerce and Magento Open Source URLs are not unique enough to allow caching by URL only. Cookie and session data in the URL can also lead to undesirable side effects, including:

  • Collisions in cache storage
  • Unwanted information leaks (e.g., French language website partially visible on an English language website, prices for customer group visible in public, etc.)

To make each cached URL totally unique, we use HTTP context variables. Context variables enable the application to serve different content on the same URL based on:

  • Customer group
  • Selected language
  • Selected store
  • Selected currency
  • Whether a customer is logged in or not

Context variables should not be specific to individual users because variables are used in cache keys for public content. In other words, a context variable per user results in a separate copy of content cached on the server for each user.

The application generates a hash based on all context variables (\Magento\Framework\App\Http\Context::getVaryString). The hash and current URL are used as keys for cache storage.

For example, let's declare a context variable that shows a drinks catalog and advertisement to adult customers only. The following code snippet will create a copy of every page in Adobe Commerce and Magento Open Source for users under the age of 18.

Copied to your clipboard
1<?php
2/**
3 * Copyright © Magento, Inc. All rights reserved.
4 * See COPYING.txt for license details.
5 */
6
7use Magento\Customer\Model\Session;
8use Magento\Framework\App\Http\Context;
9
10/**
11 * Plugin on \Magento\Framework\App\Http\Context
12 */
13class CustomerAgeContextPlugin
14{
15 public function __construct(
16 Session $customerSession
17 ) {
18 $this->customerSession = $customerSession;
19 }
20 /**
21 * \Magento\Framework\App\Http\Context::getVaryString is used to retrieve unique identifier for selected context,
22 * so this is a best place to declare custom context variables
23 */
24 public function beforeGetVaryString(Context $subject)
25 {
26 $age = $this->customerSession->getCustomerData()->getCustomAttribute('age');
27 $defaultAgeContext = 0;
28 $ageContext = $age >= 18 ? 1 : $defaultAgeContext;
29 $subject->setValue('CONTEXT_AGE', $ageContext, $defaultAgeContext);
30 }
31}

The subject->setValue argument specifies the value for newcomer context and is used to guarantee parity during cache key generation for newcomers and users who already received the X-Magento-Vary cookie.

For another example of a context class, see Magento/Framework/App/Http/Context.

X-Magento-Vary cookie#

Use the X-Magento-Vary cookie to transfer context on the HTTP layer. HTTP proxies can be configured to calculate a unique identifier for cache based on the cookie and URL. For example, our sample Varnish 4 configuration uses the following:

Copied to your clipboard
1sub vcl_hash {
2 if (req.http.cookie ~ "X-Magento-Vary=") {
3 hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
4 }
5 ... more ...
6}

Invalidate public content#

You can clear cached content immediately after a entity changes. The application uses IdentityInterface to link entities in the application with cached content and to know what cache to clear when an entity changes.

This section shows you how to tell the application what cache to clear when you change an entity.

First, your entity module must implement Magento/Framework/DataObject/IdentityInterface as follows:

Copied to your clipboard
1<?php
2/**
3 * Copyright © Magento, Inc. All rights reserved.
4 * See COPYING.txt for license details.
5 */
6
7use Magento\Framework\DataObject\IdentityInterface;
8
9class Product implements IdentityInterface
10{
11 /**
12 * Product cache tag
13 */
14 const CACHE_TAG = 'catalog_product';
15 /**
16 * Get identities
17 *
18 * @return array
19 */
20 public function getIdentities()
21 {
22 return [self::CACHE_TAG . '_' . $this->getId()];
23 }
24}

Second, the block object must also implement Magento/Framework/DataObject/IdentityInterface as follows:

Copied to your clipboard
1<?php
2/**
3 * Copyright © Magento, Inc. All rights reserved.
4 * See COPYING.txt for license details.
5 */
6
7use Magento\Framework\DataObject\IdentityInterface;
8
9class View extends AbstractProduct implements IdentityInterface
10{
11 /**
12 * Return identifiers for produced content
13 *
14 * @return array
15 */
16 public function getIdentities()
17 {
18 return $this->getProduct()->getIdentities();
19 }
20}

Adobe Commerce and Magento Open Source use cache tags for link creation. The performance of cache storage has a direct dependency on the number of tags per cache record, so try to minimize the number of tags and use them only for entities that are used in production mode. In other words, don't use invalidation for actions related to store setup.

Cacheable page checklist#

  • Pages use GET requests

  • Pages render only cacheable blocks

  • Pages render without sensitive private data; session and customer DTO objects are empty

  • Functionality specific to both current session (customer) and page should be written using JavaScript (e.g., related product listing should exclude items that are already in the shopping cart)

  • Model and block level should identify themselves for invalidation support

  • Declare a custom context variable if you plan to show different public content with the same URL

Non-cacheable page checklist#

  • Use POST requests to modify Magento state (e.g., adding to shopping cart, wishlist, etc.)

  • Blocks that can't be cached should be marked as non-cacheable in the layout. However, be aware that adding a non-cacheable block to a page prevents the full page cache from caching that page.

  • Controllers that don't use layouts should set no-cache HTTP headers

Was this helpful?
  • Privacy
  • Terms of Use
  • Do not sell my personal information
  • AdChoices
Copyright © 2022 Adobe. All rights reserved.