Magento `setup:static-content:deploy -f` Reusing Old Cache — The Wipe Sequence
You edit a LESS file, push it to production, run `bin/magento setup:static-content:deploy -f en_US`, and the old CSS still serves. The deploy reports success in under two seconds. The browser still shows the old rules. The issue is not Cloudflare, not OPcache, not the browser — it is Magento reusing the preprocessor output cached under `var/view_preprocessed`. The `-f` flag clears `pub/static` but does not always touch `view_preprocessed`. This is the exact wipe sequence we run on every Magento 2.4.4 — 2.4.9 Hyvä store to force a true LESS-to-CSS recompile, why the order of operations matters, and the one-liner that catches the nested `_module.less` reused-output trap.
Magento setup:static-content:deploy -f reusing old cache is the production-mode behavior where the static-content deploy command reports success but continues serving CSS compiled before your latest LESS edit on Magento 2.4.4 — 2.4.9 because the -f flag wipes the public static directory without invalidating the preprocessor cache under var/view_preprocessed. The fix is a five-step wipe sequence that clears both layers in the correct order — here is the exact bash, the comparison table, and the verification command we ship on every Hyvä production store at kishansavaliya.com.
The deploy is lying to you
If you ran bin/magento setup:static-content:deploy -f en_US, watched it complete in under two seconds, and the CSS at /static/frontend/<Vendor>/<theme>/en_US/<Module>/css/styles.css still contains the old rules — the deploy is not broken. It is working exactly as designed and reusing the LESS-to-CSS preprocessor output that lives in var/view_preprocessed.
Across 18 Hyvä production deployments shipped between January and May 2026, this trap caught us four times. Every time the symptom was identical: a single LESS edit, a clean git pull on live, a setup:static-content:deploy -f that finished in 1.8 seconds, and a CSS file on disk that had not changed.
The-fflag means "force overwrite of files inpub/static". It does not mean "recompile from source LESS". That distinction costs teams an hour every time.
Why this happens on 2.4.4 — 2.4.9
In production mode, Magento's view publisher splits the static-content build into two stages:
- Stage 1 — preprocess. Every
.lesssource file is resolved (imports, mixins, theme fallback), compiled to.css, and the intermediate artifacts are cached invar/view_preprocessed/pub/static/frontend/<Vendor>/<theme>/<locale>/<Module>/css/source/*.lessand*.css. - Stage 2 — publish. The compiled CSS is copied to
pub/static/frontend/<Vendor>/<theme>/<locale>/<Module>/css/.
The -f flag invalidates stage 2 only. Stage 1 sees the existing view_preprocessed artifacts, decides nothing upstream changed (file mtime comparison is shallow on nested @import chains), and copies the cached CSS back to pub/static. The publish step succeeds. The compile step never ran.
The Hyvä-specific twist
Hyvä themes use a deep @import tree — styles.less imports a theme _module.less which imports vendor module overrides which import the originating _extend.less. Magento's mtime check inspects the top-level .less file. Edit a leaf _extend.less and the top-level mtime never changes. The cache lies.
The five-step wipe sequence
This is the exact order we run on production. The order matters — wipe stage 1 before stage 2 redeploys, or stage 2 will rehydrate stage 1 from the surviving CSS in pub/static.
Step 1: Flush the module's pub/static directory
rm -rf pub/static/frontend/Kishan/savaliya/en_US/Panth_CustomizationReplace Kishan/savaliya with your vendor and theme path. Replace Panth_Customization with the module whose LESS you edited. Wiping the whole pub/static/frontend tree works too but adds 3–8 minutes to the redeploy. Targeted is faster.
Step 2: Flush view_preprocessed for the module — both .less and .css
rm -rf var/view_preprocessed/pub/static/frontend/Kishan/savaliya/en_US/Panth_Customization/css/source/*.less
rm -rf var/view_preprocessed/pub/static/frontend/Kishan/savaliya/en_US/Panth_Customization/css/source/*.css
rm -rf var/view_preprocessed/pub/static/frontend/Kishan/savaliya/en_US/Panth_Customization/css/*.cssThe first rm is the one most guides forget. Magento caches the LESS intermediates — files like _module.less and _extend.less — alongside the compiled .css. Wiping only *.css leaves the cached .less intermediates, which the preprocessor happily reuses on the next run. The compile step short-circuits and the new edit never reaches the output.
This is the trap. Three of the four production incidents we hit were teams running find var/view_preprocessed -name '*.css' -delete and assuming the cache was clean. It was not.
Step 3: Clean var/cache and var/page_cache
rm -rf var/cache/* var/page_cache/*Stage 2's publish step reads merge configuration from var/cache. Stale entries here cause the publisher to skip files it should have re-emitted. Page cache flush also evicts any Varnish or built-in FPC entries that hold the old CSS URL hashes.
Step 4: Redeploy with -f
php bin/magento setup:static-content:deploy -f en_US --theme Kishan/savaliyaThe --theme flag scopes the deploy to one theme. On a single-theme store this saves 1–4 minutes. On a multi-theme store you can omit it and deploy every theme in one pass.
This run should report "X/X 100% Y secs" with Y at least 5 seconds (often 15–30 seconds on a Hyvä store). If it still finishes in under two seconds, stage 1 still has artifacts somewhere — re-run step 2 with the full var/view_preprocessed/ path wiped.
Step 5: Verify with find
find pub/static -name '*.css' -newer var/log/system.logThis lists every CSS file modified after the last system.log rotation. If the file you expected to change is in the output, the recompile worked. If it is not, the deploy lied again — go back to step 2 and wipe the parent view_preprocessed directory, not just the module's subdirectory.
The full one-liner for production
The five steps collapsed into one bash command. Drop into a deploy script or run via SSH inside the PHP container.
docker exec --user=root -w /var/www/html kishansavaliya_php /bin/sh -c '
set -e
MOD=Panth_Customization
THEME=Kishan/savaliya
LOCALE=en_US
rm -rf pub/static/frontend/${THEME}/${LOCALE}/${MOD}
rm -rf var/view_preprocessed/pub/static/frontend/${THEME}/${LOCALE}/${MOD}/css/source/*.less
rm -rf var/view_preprocessed/pub/static/frontend/${THEME}/${LOCALE}/${MOD}/css/source/*.css
rm -rf var/view_preprocessed/pub/static/frontend/${THEME}/${LOCALE}/${MOD}/css/*.css
rm -rf var/cache/* var/page_cache/*
chown -R 1006:1008 pub/static var/view_preprocessed var/cache var/page_cache
php bin/magento setup:static-content:deploy -f ${LOCALE} --theme ${THEME}
php bin/magento cache:flush
find pub/static/frontend/${THEME}/${LOCALE}/${MOD} -name "*.css" -newer var/log/system.log
'The chown step is required if you ran the rm commands as root — Magento's CLI runs as the application user (UID 1006 on our images) and will refuse to write to root-owned directories.
-f alone vs the full wipe — what survives
| Artifact | -f alone | Full wipe |
|---|---|---|
pub/static/.../<Module>/css/*.css | Overwritten from cache | Recompiled from source |
view_preprocessed/.../css/source/*.less | Reused (the trap) | Wiped, regenerated |
view_preprocessed/.../css/source/*.css | Reused | Wiped, regenerated |
view_preprocessed/.../css/*.css | Reused | Wiped, regenerated |
var/cache merge entries | Untouched | Cleared |
| Deploy duration | 0.8–1.8 sec (lying) | 15–60 sec (honest) |
| CSS file mtime | Unchanged | Updated to now |
| Browser hard refresh fixes it? | No (file on disk is stale) | Yes (file on disk is fresh) |
Verification — three checks before you walk away
Check 1: File mtime
stat -c '%y %n' pub/static/frontend/Kishan/savaliya/en_US/Panth_Customization/css/styles.cssThe timestamp should match the deploy clock, not the prior deploy. If it is hours or days old, the recompile did not run.
Check 2: Grep for the new selector
grep -l 'your-new-class-name' pub/static/frontend/Kishan/savaliya/en_US/Panth_Customization/css/*.cssReplace your-new-class-name with a string from the LESS edit. If grep returns the CSS file, the new rule is on disk. If it returns nothing, the compile silently dropped the change — usually a LESS syntax error swallowed by Magento's error handler.
Check 3: HTTP fetch from the static URL
curl -sI https://kishansavaliya.com/static/frontend/Kishan/savaliya/en_US/Panth_Customization/css/styles.css | grep -i last-modifiedThe Last-Modified header should match the on-disk mtime. If they differ, an upstream CDN or Cloudflare cache layer is still holding the old file — purge it.
When the wipe still does not work
Three edge cases we have seen in production:
1. The LESS file has a syntax error
Magento's LESS compiler swallows parse errors silently in production mode. The compile step reports success and emits the previous CSS. Tail var/log/system.log during the deploy — any LESS error logs there.
2. The theme fallback is hiding the file
If Kishan/savaliya inherits from Hyva/default, a LESS file in the child theme can be shadowed by the parent's compiled output if the child file is missing the correct @import. Confirm with find app/design/frontend/Kishan/savaliya/Panth_Customization/web/css/ -name '*.less' and ensure the file you edited is in the path Magento walks.
3. OPcache is holding the PHP that builds the CSS path
After deploying new PHP that changes view-XML configuration, restart PHP-FPM. The static-content deploy reads view config at PHP-process startup; without a restart it uses the cached config that points to the old paths.
docker exec --user=root kishansavaliya_php pkill -USR2 php-fpmFAQ
Can I just delete all of var/view_preprocessed every time?
You can, but on a heavy Hyvä store with 8 modules and 4 locales, a full view_preprocessed wipe adds 4–8 minutes to the deploy. Targeted wipes — one module at a time — are 30 seconds.
Does this affect developer mode?
Less often, but yes. Developer mode compiles LESS on-request, but var/view_preprocessed still caches intermediates. After a heavy sed-and-edit storm on local, the same wipe pattern unsticks stale LESS imports. Local is in developer mode so the symptom is less common — but it does occur.
What about the Hyvä Tailwind build?
Hyvä themes use Tailwind for utilities and LESS only for module-specific overrides. The Tailwind build (npm run build-prod under web/tailwind/) is a separate pipeline that produces styles.css. If your edit was to a .css source file under Tailwind, run the Tailwind build, not the Magento deploy. Both wipes can be needed if the change touched both pipelines.
Does setup:static-content:deploy on Magento 2.4.7 and earlier behave differently?
The behavior on 2.4.4 through 2.4.9 is consistent — the -f flag has not changed semantics in that range. Earlier versions (2.4.3 and below) had a different cache invalidation pattern but they are out of support and not relevant in 2026.
Can I script a pre-commit hook to wipe on every deploy?
Yes — and we do, on production. The full-wipe one-liner above lives as scripts/deploy-static.sh in our deploy repo and runs after every git pull on live. The 30-second cost is worth the certainty.
What about cache:flush — is that not enough?
No. cache:flush clears Magento's application cache (config, EAV, layout). It does not touch var/view_preprocessed or pub/static. The CSS pipeline lives outside Magento's standard cache invalidation tree.
Where this fits in the deploy flow
On a Magento 2.4.4 — 2.4.9 Hyvä production store, the safe deploy order after a LESS edit is:
git pullon live.- If
composer.lockchanged:composer install --no-dev --optimize-autoloader. - If
app/etcoretc/module.xmlchanged:setup:upgrade. - If PHP code changed:
setup:di:compile. - The five-step LESS wipe sequence from this post.
cache:flush.- Purge Cloudflare (or whichever CDN sits in front of
/static/). - Verify with the three checks above.
Skip step 5 and you ship a deploy that looks green but serves yesterday's CSS. We have done that. The merchant noticed before we did.
References
Related reading
- Magento slow checkout — the actual 3 fixes
- Magento 2.4.9 upgrade — the 5 traps Adobe did not document
- Hyvä theme development service
I run fixed-scope Magento 2.4.4 — 2.4.9 deploy hardening sprints — wipe sequences scripted, deploy hooks added, Cloudflare purge integrated, verification baked in. Fixed quote from $499 audit · $2,499 sprint · ~12h @ $25/hr. See hire me.