← Back to blog

Magento 2 Cache Types Explained: Clean, Flush, Custom

Rodrigo Biazzi

Magento 2 has more than a dozen cache types, and the usual advice when something looks wrong is to flush all of them. That works, but it also throws away the work of every visitor since the last flush and slows the store down until the caches warm up again. Knowing what each cache type holds lets you clean only what changed and understand why a change does not show up. This article explains the cache types in Magento Open Source and Adobe Commerce 2.4.8, the difference between clean and flush, and how to add your own cache type.

Listing the cache types

bin/magento cache:status

The output lists each cache type by its code and whether it is enabled. The admin shows the same list under System, Tools, Cache Management, with a label, a description and an invalidated flag. The exact list depends on the installed modules. A core 2.4.8 install includes the types below, and extensions can add their own.

What each cache type holds

CodeWhat it storesClean it when
configMerged XML config and system config valuesConfig XML or admin settings changed
layoutMerged layout XML per handleLayout XML changed
block_htmlRendered HTML of blocks with cache settingsBlock output or its data changed
collectionsResults of collections that use cacheUnderlying data changed
reflectionReflection data used by the Web APIAPI interfaces changed
db_ddlTable structure metadataDatabase schema changed
compiled_configCompilation outputAfter DI compilation
eavEAV entity types and attribute metadataAttributes changed
customer_notificationFlags telling active customer sessions to reload their dataRarely needed
config_integrationIntegration configurationIntegration config changed
config_integration_apiIntegration API configurationIntegration API config changed
graphql_query_resolver_resultCached results of some GraphQL resolversResolver data changed
full_pageBuilt in full page cacheStorefront content changed
config_webserviceWeb API configurationwebapi.xml changed
translateMerged translationsTranslation CSV or inline translations changed

A few of these deserve more detail.

config

This is the most important one. It holds the merged result of every module's XML configuration plus system configuration values from the database. Almost every request reads from it. Cleaning it forces Magento to rebuild configuration on the next request, which is expensive. When many processes try to rebuild it at once after a clean, you see a short spike in load and response times.

layout and block_html

The layout cache holds the merged XML for each handle combination, not rendered HTML. The block HTML cache holds the output of blocks that define cache keys and lifetimes, such as menus and footer blocks. If you change a template and see no change on the storefront, it is usually block_html or full_page holding the old output.

full_page

This is the built in full page cache. When Varnish is configured as the full page cache application, Magento sends purge requests to Varnish when this cache type is cleaned. Cleaning full_page with Varnish in use clears Varnish, not a local storage. The Varnish guide explains how tags and purges work.

graphql_query_resolver_result

This type caches the results of selected GraphQL resolvers on the server side, separate from HTTP level caching of GraphQL GET requests. It matters for headless storefronts. See the GraphQL caching guide for how the layers fit together.

compiled_config

Stores the compiled DI configuration used in production mode. After running setup:di:compile it is replaced as part of the process.

Clean versus flush

These two commands sound similar and behave quite differently.

bin/magento cache:clean
bin/magento cache:clean config layout

bin/magento cache:flush

cache:clean removes Magento's entries for the given cache types, or for all enabled types if you give none. It works through Magento's cache tags, so it only touches what Magento put there.

cache:flush empties the cache storage behind the cache frontends completely. With the file backend that means the cache folders. With Redis it means the configured database. Anything else stored in the same place is gone too. If another application or a second Magento instance shares that Redis database, a flush removes their data.

The admin has the same two choices: Flush Magento Cache is a clean, and Flush Cache Storage is a flush. The naming is confusing. In daily work, clean is almost always what you want. Flush is for when you suspect the storage itself has stale data Magento does not know about.

The invalidated status

When you save certain things in the admin, such as configuration or layout updates, Magento marks the affected cache types as invalidated instead of cleaning them right away. The admin shows a message saying some cache types are invalidated. Nothing is rebuilt until someone cleans those types. That is a deliberate choice so that a series of admin changes does not rebuild configuration after each save. Clean the invalidated types when you are done:

bin/magento cache:clean config full_page

Product, category and CMS saves are different. They clean the specific cache tags for the affected entities automatically, so the related full page cache entries are removed without anyone pressing a button.

Enabling and disabling cache types

bin/magento cache:disable block_html full_page
bin/magento cache:enable

The enabled state is stored in app/etc/env.php under cache_types. In production every cache type should be enabled. A disabled config cache in particular slows every request dramatically.

Locally, people often disable block_html, layout and full_page while working on templates and layout. That works, but it hides caching bugs, such as a block that shows the wrong customer's data because it caches per page instead of per customer. Test with all caches enabled before you ship.

Creating your own cache type

If your module caches its own data, for example an external API response or an expensive computation, give it its own cache type. Admins can then see it, disable it and clean it independently.

Declare the type in etc/cache.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Cache/etc/cache.xsd">
    <type name="vendor_feed" translate="label,description" instance="Vendor\Feed\Model\Cache\Type\Feed">
        <label>Vendor Feed</label>
        <description>Cached responses from the external feed API</description>
    </type>
</config>

Then the class, which scopes all entries under one tag:

<?php
declare(strict_types=1);

namespace Vendor\Feed\Model\Cache\Type;

use Magento\Framework\App\Cache\Type\FrontendPool;
use Magento\Framework\Cache\Frontend\Decorator\TagScope;

class Feed extends TagScope
{
    public const TYPE_IDENTIFIER = 'vendor_feed';
    public const CACHE_TAG = 'VENDOR_FEED';

    public function __construct(FrontendPool $cacheFrontendPool)
    {
        parent::__construct($cacheFrontendPool->get(self::TYPE_IDENTIFIER), self::CACHE_TAG);
    }
}

To use it, inject the type class and check whether the cache type is enabled through Magento\Framework\App\Cache\StateInterface:

<?php
declare(strict_types=1);

namespace Vendor\Feed\Model;

use Magento\Framework\App\Cache\StateInterface;
use Magento\Framework\Serialize\SerializerInterface;
use Vendor\Feed\Model\Cache\Type\Feed;

class FeedProvider
{
    public function __construct(
        private readonly Feed $cache,
        private readonly StateInterface $cacheState,
        private readonly SerializerInterface $serializer,
        private readonly FeedClient $client
    ) {
    }

    public function get(string $sku): array
    {
        $key = 'vendor_feed_' . $sku;
        $enabled = $this->cacheState->isEnabled(Feed::TYPE_IDENTIFIER);

        if ($enabled) {
            $cached = $this->cache->load($key);
            if ($cached !== false) {
                return $this->serializer->unserialize($cached);
            }
        }

        $data = $this->client->fetch($sku);

        if ($enabled) {
            $this->cache->save($this->serializer->serialize($data), $key, [Feed::CACHE_TAG], 3600);
        }

        return $data;
    }
}

After enabling the module, run bin/magento cache:enable vendor_feed so the new type is active. New cache types are not always enabled automatically on existing installs. FeedClient here stands for your own API client class.

FAQ

What is the difference between cache:clean and cache:flush in Magento 2?

cache:clean removes Magento entries by cache type and tag. cache:flush empties the whole cache storage, including anything else stored in the same backend.

Why does the admin say some cache types are invalidated?

Some admin saves mark cache types as invalidated instead of cleaning them immediately. Clean those types when you finish your changes.

Which cache type holds my template output?

Rendered block output is in block_html and the complete page is in full_page, or in Varnish if you use it. Clean those after template changes.

Should any cache type be disabled in production?

No. All cache types should be enabled in production. Disabling config or layout cache in particular slows every request.

I am available for freelance Magento and Adobe Commerce work, including performance and caching problems. If you need help with this, get in touch.

Related articles