Magento 2 Cache Types Explained: Clean, Flush, Custom
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
| Code | What it stores | Clean it when |
|---|---|---|
| config | Merged XML config and system config values | Config XML or admin settings changed |
| layout | Merged layout XML per handle | Layout XML changed |
| block_html | Rendered HTML of blocks with cache settings | Block output or its data changed |
| collections | Results of collections that use cache | Underlying data changed |
| reflection | Reflection data used by the Web API | API interfaces changed |
| db_ddl | Table structure metadata | Database schema changed |
| compiled_config | Compilation output | After DI compilation |
| eav | EAV entity types and attribute metadata | Attributes changed |
| customer_notification | Flags telling active customer sessions to reload their data | Rarely needed |
| config_integration | Integration configuration | Integration config changed |
| config_integration_api | Integration API configuration | Integration API config changed |
| graphql_query_resolver_result | Cached results of some GraphQL resolvers | Resolver data changed |
| full_page | Built in full page cache | Storefront content changed |
| config_webservice | Web API configuration | webapi.xml changed |
| translate | Merged translations | Translation 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
Magento 2 Redis Setup for Cache and Sessions
Configure Redis for Magento 2 cache, page cache and sessions: env.php settings, session locking, eviction policies, preload keys and the L2 cache backend.
Magento 2 Blackfire Profiling: Pages, CLI and Tests
Profile Magento 2 with Blackfire: probe and agent setup, profiling pages and bin/magento commands, reading call graphs and adding performance assertions.
Magento 2 Cart Price Rules: Add a Custom Condition
Add a custom condition to Magento 2 cart price rules: the combine event, a condition model with validate, promo rule attributes and performance traps to avoid.
Magento 2 CDN: Cloudflare vs Fastly Setup Guide
Put a CDN in front of Magento 2: Fastly as an edge full page cache, Cloudflare for static and media, real client IP, purging and settings that break things.