Cache Flush vs. Cache Clean in Deployments: What You Actually Need and When
AI generated
CI/CD
.yml
GitLab · CI/CD · Magento Cache · Deployment
Cache Flush vs. Cache Clean
what you actually need in deployments, and when

Anyone who reflexively runs cache:flush after every deployment clears more than necessary and drives up load through needless cache regeneration. Precise cache invalidation after a release is a technical decision, not a habit.

10 min read cache:flush · cache:clean · Redis · cache types · deployment Magento 2 · GitLab CI · Performance

1. Magento cache types and what they store

Magento maintains a set of named cache types, each caching a different category of data. The config cache holds merged configuration data from all XML files. The layout cache stores layout update handles. The block_html cache holds rendered block HTML output. The full_page cache (FPC) stores complete page responses. There are also collections, db_ddl, compiled_config, reflection, eav, customer_notification, target_rule, and more.

The central misunderstanding: not every cache type is invalidated by a code deployment. A new theme release changes block_html and full_page, but not necessarily db_ddl or eav. A configuration change invalidates config and compiled_config, but not full_page. Anyone who blindly runs cache:flush after every deployment also wipes out caches that could keep working intact and performance friendly, at the cost of heavy load during the first warmup after the release.

The list of Magento cache types is not fixed: third party modules can register their own cache types. bin/magento cache:status shows the full list of registered cache types along with their current status. It is worth checking this list after installing new modules to understand which new cache types were added and which deployments need to invalidate them. Undocumented third party caches are a frequent source of inconsistency problems after deployments.

2. cache:flush vs. cache:clean: the technical difference

bin/magento cache:flush clears the entire cache storage. With Redis that means running FLUSHDB on the configured Redis database. All data is deleted, regardless of which cache type it belongs to. It is a radical step that guarantees no stale data remains at all, and it is also the step with the highest performance consequence: after a flush, Magento has to rebuild every cache type from scratch.

bin/magento cache:clean, on the other hand, only invalidates Magento's own cache entries while leaving third party data in the same storage intact. It respects cache tags and can be limited to specific cache types: bin/magento cache:clean config block_html invalidates only those two types. For most deployments, cache:clean with the actually affected cache types is the more precise and more performant choice.

deploy:production:
  stage: deploy
  script:
    - ssh "${DEPLOY_USER}@${DEPLOY_HOST}" bash -s << 'DEPLOY'
        set -euo pipefail
        cd "${DEPLOY_PATH}/current"

        # Step 1: Flush config-related caches BEFORE symlink switch
        # These must be cleared because the new code may rely on new config
        php bin/magento cache:clean config compiled_config

        # Step 2: Static content deploy (generates new assets)
        php bin/magento setup:static-content:deploy en_US -f -j 4

        # Step 3: After symlink switch, clean layout and HTML caches
        # New templates and blocks need fresh rendering
        php bin/magento cache:clean layout block_html full_page

        # Step 4: Only use cache:flush when the storage backend must be reset
        # e.g., after changing the Redis database or prefix, NOT for routine deployments
        # php bin/magento cache:flush  # Use sparingly!
      DEPLOY

3. When cache:flush is really necessary

cache:flush is the right choice in a few clearly defined situations. First, when the cache storage itself is being swapped, for example a new Redis instance or a changed database prefix configuration. In that case the new storage holds no old data anyway, so a flush is either empty or genuinely necessary. Second, when a serious fault in the cache backend is suspected that has led to inconsistent data. Third, right after the initial system setup, when the cache does not yet hold any meaningful data.

In a normal Magento release deployment, cache:flush is almost never the right choice. It is the solution for exceptional situations, not for the standard process. Teams that run it routinely after every deployment usually do so out of uncertainty, "that way nothing stale can possibly come from the old cache", but they pay for it with noticeably higher load and longer response times in the minutes after the deployment, until the cache warms back up.

4. When cache:clean is the better choice

For most Magento deployments, cache:clean with explicitly listed cache types is the right choice. For a pure PHP code deployment with no configuration changes, at minimum config, compiled_config, block_html, and full_page need to be cleared. For a frontend only release that changes just templates and CSS, layout, block_html, and full_page are enough. For a configuration change in XML files, config and compiled_config are the relevant ones.

Working out which cache types are affected by a specific release can be automated in the deployment process: the CI system can determine, based on the changed files, which cache types need invalidating. If only files under app/design/ changed, db_ddl, eav, and collections do not need to be cleared. This precise invalidation is the difference between a deployment with a short cache warmup and one that puts the servers under heavy load for minutes.

5. The correct cache sequence in a deployment

The order of cache commands in a deployment matters just as much as the commands themselves. Before the symlink switch, config and compiled_config should be cleared so the new configuration is loaded immediately on the first request against the new release. setup:static-content:deploy runs after that and generates new static files. The symlink switch only happens once the new release directory is fully prepared.

After the symlink switch, layout, block_html, and full_page are cleared. These caches can only be cleared once the web server is already pointing at the new release, because they get repopulated on the next request with the new template output. If this sequence is reversed, clearing full_page first and only then switching the symlink, Magento briefly loads the old code and uses it to generate a new full page cache, which the new release would then have to invalidate all over again immediately.

6. Placing cache commands correctly in GitLab CI

In a GitLab pipeline, cache operations should live inside the deploy job, not in a separate post deploy job. The reason: if the deploy job fails after the cache has already been cleared, production is left without cache data even though no new release is actually live. Cache cleanup has to be part of the atomic deployment sequence, alongside the symlink switch, not a step that runs afterward.

A verify job after the deploy can call cache:status to check that every cache type is enabled and reachable. That is not a cache invalidation, it is a state check, and an important signal that the cache backend is configured correctly. If cache:status reports a missing or disabled cache type, that points to a configuration problem that needs to be fixed before the next deployment.

7. Redis cache: special considerations for flushing

With Redis as the cache backend, cache:flush has an especially far reaching effect because it runs FLUSHDB on the configured database. If several Magento instances or other applications share the same Redis database, which is not recommended but does happen, cache:flush wipes their data too. That is why every Magento instance needs its own Redis database (or its own Redis instance) if cache:flush is going to be used even occasionally.

Another Redis consideration: if Magento runs cache:clean or cache:flush while the Redis server is under heavy load, the command can block. In production environments it is a good idea to keep a short monitoring window after any cache command: if Redis CPU or memory spikes unexpectedly, that can indicate a regeneration effect that fired too early. This typically happens when many requests try to generate the same cache entry at the same time, the classic cache stampede problem after a flush.

verify:cache:
  stage: verify
  script:
    - ssh "${DEPLOY_USER}@${DEPLOY_HOST}" bash -s << 'VERIFY'
        set -euo pipefail
        cd "${DEPLOY_PATH}/current"

        # Verify all expected cache types are enabled
        php bin/magento cache:status

        # Confirm Redis is reachable and responding
        php -r "
          \$redis = new Redis();
          \$redis->connect('${REDIS_HOST}', ${REDIS_PORT});
          echo 'Redis PING: ' . \$redis->ping() . PHP_EOL;
          echo 'Redis DB keys: ' . \$redis->dbSize() . PHP_EOL;
        "
      VERIFY
  when: on_success
  dependencies:
    - deploy:production

7b. Opcache and cache commands working together

A cache layer that often gets forgotten next to Magento's own cache is the PHP opcache. The opcache stores compiled PHP bytecode versions and speeds up execution considerably. After a deployment that changed PHP files, the opcache also has to be cleared, otherwise Magento may keep running the old PHP code version even though the files on the server have already been updated. This happens especially often with symlink based deployments, when nginx picks up the new symlink path but the PHP opcache still holds the old files from its inode cache.

The correct sequence: after the symlink switch, the opcache is cleared via php -r 'opcache_reset();' on the CLI. Alternatively, PHP-FPM can be sent a reload signal (not restart) to replace its workers one by one, which also clears the opcache. In Docker based setups, an explicit php-fpm reload after the symlink switch is recommended. The interplay between Magento cache commands and a PHP opcache reset is a frequently overlooked cause of unexplained behavior changes right after deployments.

A diagnostic tool for opcache problems: php -r 'var_dump(opcache_get_status(true));' shows the current state of the opcache and whether the invalidation step actually took effect. If entries with old timestamps are still present after an opcache reset, that points to a configuration issue with opcache.validate_timestamps. In production environments, validate_timestamps is often disabled (set to 0) to avoid opcache overhead, in which case the reset must be run explicitly, since the opcache would otherwise not notice file changes at all.

Bottom line for the deployment flow: Magento cache commands (cache:clean) and a PHP opcache reset are two independent layers, and both are needed for complete cache invalidation after a deployment. Anyone who only accounts for one of the two layers will run into unexplained, inconsistent behavior changes after certain deployments that are hard to reproduce and hard to debug.

8. Cache strategy during a rollback

A rollback reverts the code to the previous release, but the cache may already contain data from the new release. That can cause inconsistencies if the new release introduced new cache structures or formats. The safe rollback cache strategy is therefore: after switching the symlink back to the old release, always run cache:clean config compiled_config block_html full_page layout to make sure the cache is consistent with the rolled back code.

Unlike the deployment case, a somewhat more aggressive cache clean is advisable during a rollback, because the rollback itself is already an exceptional situation. The performance hit from the warmup is acceptable here, it matters more that the rolled back release works correctly than that the cache is optimally populated. A cache:flush during a rollback is, in many cases, the safer choice, even though it briefly puts the servers under load.

9. Comparison: reflexive vs. targeted invalidation

Situation Recommended command Reasoning Performance effect
Code deployment cache:clean config block_html full_page Clear only the affected types Minimal warmup load
Rollback cache:flush Exceptional situation, consistency matters more Higher load, acceptable
Redis backend swap cache:flush New storage, old data is obsolete One time, planned
Frontend only change cache:clean layout block_html full_page No configuration impact Very low warmup load
Routine after deploy cache:flush (wrong!) Clears every cache type needlessly High load, extended TTFB

The table makes it clear: cache:flush is not a standard deployment command, it is an emergency tool. Whoever invalidates in a targeted way reduces server load after the release and shortens the time until the shop delivers full performance again. That matters especially for deployments during peak hours.

10. Summary

The difference between cache:flush and cache:clean is not an academic nuance, it has a direct impact on shop performance in the minutes after a deployment. cache:flush clears everything and produces maximum regeneration load. cache:clean with explicit cache types is more precise, leaves unaffected caches alone, and reduces warmup load. For rollbacks, cache:flush is acceptable because of the exceptional situation; for regular deployments, targeted cache:clean is the right choice.

The order of the cache commands matters just as much as which command is chosen: config and compiled_config before the symlink switch, block_html, layout, and full_page after the symlink switch. This sequence ensures the cache stays consistent with the active code at every step of the deployment.

Documenting these rules once, explicitly, as a commented deployment sequence in the GitLab pipeline prevents future team members or AI assisted code changes from reflexively adding a cache:flush. The best pipeline documentation is the one that explains, right in the YAML as a comment, why which command runs in which order, and why cache:flush is deliberately avoided.

One final rule of thumb: when the choice between cache:flush and cache:clean is unclear, cache:clean with a broad list of cache types is almost always the safe option. Worst case, one cache entry does not get cleared and has to be cleared manually afterward. That is far less problematic than an unnecessary flush that puts the shop under heavy load for several minutes. Performance problems after deployments caused by a cache stampede are often harder to diagnose than a single stale cache entry.

Cache Flush vs. Cache Clean: The Essentials at a Glance

cache:clean for deployments

cache:clean config compiled_config block_html full_page, clear only the affected types, not everything.

cache:flush for exceptions

Only for rollbacks, backend swaps, or suspected inconsistency. Not a standard deployment step.

Order matters

config/compiled_config BEFORE the symlink switch. block_html/layout/full_page AFTER the symlink switch.

Avoid Redis stampedes

Cache warmup after a flush creates heavy load. Cache clean with targeted types minimizes this effect.

11. FAQ: Cache Flush vs. Cache Clean for Magento

1Difference between cache:flush and cache:clean?
Flush clears the entire storage (FLUSHDB with Redis). Clean invalidates only Magento's own entries and can be limited to specific types.
2Which cache types after a code deployment?
At minimum: config, compiled_config, block_html, full_page, layout. For pure frontend changes, config and compiled_config can be skipped.
3When cache:flush instead of cache:clean?
Rollback, backend swap, cache corruption, initial system setup. Not for regular deployments.
4What is a cache stampede?
Many requests regenerate the same empty cache at once. After cache:flush this happens for every type. cache:clean minimizes the effect.
5Why not run cache:flush after every deployment?
It clears caches the deployment never touched and needlessly increases regeneration load. cache:clean with the affected types has the same effect with fewer side effects.
6Does cache:clean delete third party data in Redis?
No. cache:clean respects cache tags and only deletes Magento's own entries. cache:flush runs FLUSHDB and deletes everything.
7Order of cache commands in a deployment?
config/compiled_config BEFORE the symlink switch. block_html/layout/full_page AFTER the symlink switch.
8What does cache:status do?
Shows which cache types are enabled and reachable. Invalidates nothing. Useful in the verify job after deployment.
9How long does cache warmup take after a flush?
Depends on traffic and page count, minutes with full_page. Cache warmup scripts (automated URL calls) shorten this time.
10Clear cache before or after setup:upgrade?
setup:upgrade runs a cache flush itself. After setup:upgrade, cache:flush is appropriate as an exception, since the DB schema and DI container may have changed.

The most important practical rule: better to flush once too often than to leave production in an inconsistent cache state, but better to clean targeted tags than to needlessly invalidate every cache and waste warmup time.

A clearly documented cache concept in the deployment playbook saves hours of troubleshooting after a release and protects against classic pitfalls like stale layout caches or configuration values that never got refreshed.