Magento 2: Clean Fastly or Varnish Cache by Cache Tag Programmatically

This article shows how you can clean Fastly Cache or Varnish Cache by cache tags in Magento.

Fastly has an observer that listens to the event clean_cache_by_tags.

vendor/fastly/magento2/etc/events.xml (github)


<event name="clean_cache_by_tags">
    <observer name="flush_fastly_cdn" instance="Fastly\Cdn\Observer\InvalidateVarnishObserver"/>
</event>

The \Fastly\Cdn\Observer\InvalidateVarnishObserver class further calls the \Fastly\Cdn\Model\PurgeCache::sendPurgeRequest($pattern) method which finally cleans the Fastly Cache utilizing \Fastly\Cdn\Model\Api.

Magento’s Cache_Invalidate module has a similar event observer:

vendor/magento/module-cache-invalidate/etc/events.xml


<event name="clean_cache_by_tags">
    <observer name="invalidate_varnish" instance="Magento\CacheInvalidate\Observer\InvalidateVarnishObserver"/>
</event>

The Magento\CacheInvalidate\Observer\InvalidateVarnishObserver class further calls the \Magento\CacheInvalidate\Model\PurgeCache::sendPurgeRequest($tags) method which finally cleans the Varnish Cache.

We can simply fire the clean_cache_by_tags event and pass the cache tags as an object to the event.

Cache tags can be of CMS Page, Block, Product or Category whose cache needs to be cleared from Fastly or Varnish.

Here’s an example class. The class reference is taken from the core class: \Magento\InventoryCache\Model\FlushCacheByCacheTag.

app/code/YourNamespace/YourModule/Model/FlushCacheByTag.php


<?php
declare(strict_types=1);

namespace YourNamespace\YourModule\Model;

use Magento\Framework\EntityManager\EventManager;
use Magento\Framework\Indexer\CacheContextFactory;
use Magento\Framework\App\CacheInterface;

/**
 * Clean cache for given cache tag.
 */
class FlushCacheByTag
{
    /**
     * @var CacheContextFactory
     */
    private $cacheContextFactory;

    /**
     * @var EventManager
     */
    private $eventManager;

    /**
     * @var CacheInterface
     */
    private $appCache;

    /**
     * @param CacheContextFactory $cacheContextFactory
     * @param EventManager $eventManager
     * @param CacheInterface $appCache
     */
    public function __construct(
        CacheContextFactory $cacheContextFactory,
        EventManager $eventManager,
        CacheInterface $appCache
    ) {
        $this->cacheContextFactory = $cacheContextFactory;
        $this->eventManager = $eventManager;
        $this->appCache = $appCache;
    }

    /**
     * Clean cache for given entity and entity ids.
     *
     * @param string $cacheTag
     * @param array $entityIds
     * @return void
     */
    public function execute(string $cacheTag, array $entityIds): void
    {
        if ($entityIds) {
            $cacheContext = $this->cacheContextFactory->create();
            $cacheContext->registerEntities($cacheTag, $entityIds);
            $this->eventManager->dispatch('clean_cache_by_tags', ['object' => $cacheContext]);
            $this->appCache->clean($cacheContext->getIdentities());
        }
    }
}

The implementation of the above class to clear Fastly Cache for certain pages, blocks, products and categories is shown below:


$pageIds = [1, 2, 3, 4];
$this->flushCacheByTag->execute(Page::CACHE_TAG, $pageIds);

$blockIds = [3, 4, 5, 6];
$this->flushCacheByTag->execute(Block::CACHE_TAG, $blockIds);

$productIds = [11, 22, 23, 45];
$this->flushCacheByTag->execute(Product::CACHE_TAG, $productIds);

$categoryIds = [7, 15];
$this->flushCacheByTag->execute(Category::CACHE_TAG, $categoryIds);

Hope this helps. Thanks.