
Magento 2 static content deploy (bin/magento setup:static-content:deploy) copies and compiles theme assets into pub/static for every area, theme, and locale you ask for. Strategy (quick, standard, compact) only matters when you deploy more than one locale. The biggest time savings come from scoping themes and locales tightly, adding parallel jobs, and skipping work Hyva never needs.
Static content deployment is the step most teams treat as a black box. It runs in the pipeline, it takes as long as it takes, and nobody touches it until a release window slips because the build ran for twenty minutes. This guide breaks the command down into the parts you can actually control, explains what each strategy does on disk, and shows how the picture changes on a Hyva storefront, where most of the classic Luma work simply does not exist.
What setup:static-content:deploy actually does
In production mode, Magento does not generate static view files on demand. Every CSS file, JavaScript file, font, image, and HTML template a browser can request has to already exist under pub/static, organized by area (frontend or adminhtml), theme (for example Vendor/theme), and locale (for example en_US). The deploy command walks the theme fallback chain for each combination, resolves which module or theme file wins, runs preprocessing (LESS compilation on Luma themes, translation dictionaries, RequireJS config merging), and writes the result.
Adobe’s command reference for static view file deployment lists the rules worth memorizing:
- In production mode, files must be deployed with this command. In default and developer mode, Magento generates files on demand and the tool refuses to run unless you pass
-f(--force). - Before a manual deploy, clear the contents of
pub/staticexcept the.htaccessfile. - Run it as the file system owner, not root.
- The default for
--jobsis0, meaning no parallel processing unless you ask for it. - Each run changes the deployment version, which is what invalidates browser and CDN caches for signed static URLs.
That last point is easy to forget. With static content signing enabled (the default), Magento inserts a version<timestamp> path segment into every static URL. If you build on one server and ship artifacts to another, Adobe’s guidance is to carry pub/static/deployed_version.txt with the build so production serves the matching version.
Quick vs standard vs compact: what each strategy writes
The -s (--strategy) flag picks how files are laid out when several locales share a theme. Adobe’s deployment strategies documentation describes them this way, and the details matter more than the one-line summaries suggest.
Standard is the regular process. It deploys every static view file for every package through the asset publisher, with no shortcuts. Every area, theme, and locale directory is complete and self-contained.
Quick is the default. For each theme it picks one locale and deploys it fully, the same as standard. For every other locale, it deploys only the files that differ for that locale, and copies everything else (CSS, images, fonts, anything locale-independent) from the first one. You get full directories per locale, fast, at the cost of a lot of duplicate files on disk.
Compact avoids duplication. Instead of copying shared files into every locale directory, it stores them in base directories at the lowest scope they apply to, such as <area>/<theme>/default for files shared by all locales of a theme, or base/Magento/base/default for files shared by everything. It then writes a map.php (used by the asset repository to build URLs) and a requirejs-map.js (used by RequireJS) for each area, theme, and locale combination so the storefront requests files from the right place.
| Strategy | How shared files are handled | Disk usage | Deploy time with many locales | Main risk |
|---|---|---|---|---|
standard |
Every file published for every locale | Highest | Slowest | None beyond time |
quick (default) |
First locale built fully, others copy shared files | High (duplicates) | Fast | Duplicated files fill disk on large locale counts |
compact |
Shared files stored once in base scopes, resolved through map files |
Lowest | Moderate | Extensions that build static URLs by string concatenation can 404 |
Two cautions on compact. First, Adobe tells extension developers to build asset URLs with \Magento\Framework\View\Asset\Repository::createAsset() because concatenated URLs bypass the map files and can produce missing assets. A third-party module that hardcodes a path is the usual culprit when compact “breaks styles.” Second, compact has had its own bugs: Adobe shipped a quality patch (ACSD-46815) for static content deploy failing under the compact strategy, so check your version against the Quality Patches Tool before switching.
If you run a single locale per theme, none of this changes your output in any meaningful way. Adobe says as much: use the strategy option only if you have more than one locale.
The flags that actually change deploy time
Most slow deploys are slow because they build far more than the store serves. A default run deploys every installed theme (including Luma and Blank, even if no store view uses them), for every area, for whatever locales you list. Here is what each lever does.
Scope themes and locales explicitly
Pass --theme (repeatable) and list only the locales your store views use. For the admin, most teams need one locale. Use --exclude-theme if scripting the list is easier than naming every theme. Adobe documents that when you pass positional <languages> and --language together, the positional list wins, so pick one style and stick to it.
Split the admin and frontend runs
Running --area=adminhtml and --area=frontend as separate commands lets you give each its own theme and locale list. The admin almost never needs the full set of storefront locales.
Parallel jobs with -j
-j sets the number of parallel jobs. The default of 0 means everything runs in one process. On a build machine with spare cores, raising it is usually the cheapest speedup available. Watch memory: each job is a PHP process, and a starved CI runner will swap and end up slower than a single job.
–no-parent
Available from Adobe Commerce 2.4.2, --no-parent skips generating files for parent themes. Adobe recommends it unless you explicitly serve a parent theme. On Hyva, your custom theme typically inherits Hyva/default, which no store view uses directly, so building it is wasted time.
Skip asset types you do not ship
The --no-javascript, --no-css, --no-less, --no-images, --no-fonts, --no-html, --no-misc, and --no-html-minify flags skip whole categories. Use them carefully on Luma, where they can strip files the storefront needs. On Hyva, several of them are exactly right.
How Hyva changes the static deploy picture
A Luma storefront leans on static deploy for real work: LESS compilation, RequireJS configuration, optional JavaScript bundling, and HTML minification. Hyva removes most of that. Styling comes from a Tailwind build, and the storefront ships Alpine.js components inline in templates rather than a RequireJS dependency graph.
Hyva’s own guide to deploying a Hyva theme to production spells out the order of operations:
- Build the stylesheet first with
npm run buildin the theme’sweb/tailwinddirectory (Hyva 1.1.x usednpm run build-prod). In CI, install withnpm ci --ignore-scriptsso you get the exact lockfile versions and avoid running install scripts. - Run static content deploy, scoped tightly. Hyva’s example deploys the admin theme for
en_USonly, then the frontend theme for its storefront locales with--no-parent --no-less --no-js-bundle --no-html-minify. - Ship
pub/staticto production with rsync, SCP, or your pipeline, then flush cache.
Hyva also recommends turning off Magento’s built-in minification and bundling for Hyva themes, since there is nothing for them to improve. Do the Tailwind build on a build or CI machine, not on production, so you never need Node.js on your web servers.
A practical Hyva pipeline therefore looks like this:
# 1. Tailwind production CSS
npm --prefix app/design/frontend/Vendor/theme/web/tailwind ci --ignore-scripts
npm --prefix app/design/frontend/Vendor/theme/web/tailwind run build
# 2. Admin: one theme, one locale
bin/magento setup:static-content:deploy -f -j 4 --area=adminhtml \
--theme=Magento/backend --no-parent en_US
# 3. Storefront: only the Hyva child theme, only live locales
bin/magento setup:static-content:deploy -f -j 4 --area=frontend \
--theme=Vendor/theme --no-parent --no-less --no-html-minify en_US fr_CA
If the compiled CSS looks wrong after this, the problem is almost always upstream of static deploy. Our guide to the Hyva Tailwind production build covers content globs and safelists, the two most common reasons classes go missing.
What about mixed Luma and Hyva stores?
Stores mid-migration often run Hyva on the storefront while a Luma fallback theme still serves checkout or a secondary store view. In that case keep the Luma theme in its own deploy command with LESS enabled, and apply the Hyva-only skips to the Hyva theme command. One command with --no-less across both will break the Luma side.
Go-based deployers for Hyva
The open source elgentos magento2-static-deploy project is an experimental Go replacement for the native command. It skips the Magento bootstrap, copies theme files in parallel, compiles only email CSS, and detects Hyva themes automatically, handing Luma themes back to bin/magento. Its README reports a frontend deploy dropping from about 115 seconds to under a second, though its own benchmark compares different file counts, so treat the headline multiplier as a vendor claim. It also lists what it does not do: RequireJS config merging, JavaScript translation generation, bundling, minification, and SRI hash generation. Test it against your native output before trusting it in production, especially if you rely on any of those.
Adobe Commerce Cloud: build phase vs deploy phase
On Adobe Commerce Cloud you rarely run the command by hand. ece-tools runs it for you, controlled by variables in .magento.env.yaml. Where it runs matters more than any flag.
- Deploy phase (the default): static content is generated while the site is in maintenance mode and written to the mounted
pub/staticdirectory. Adobe calls this the least optimal choice, because copying every file onto the mount takes time while the store is down. - Build phase (the recommended “ideal state”): static content is generated during the build and symlinked into place, which supports zero-downtime deployments. The catch is that the database is not available during build, so locales and store structure must come from
app/etc/config.php. You get them there withconfig:dump, and you must re-run it whenever you add a website, store, or store view. - On demand (
SCD_ON_DEMAND): files are generated on first request. Adobe recommends it only for integration environments and explicitly warns against using it in production.
The build-stage variables that map to the CLI flags are documented in Adobe’s build variables reference:
| Variable | What it controls | Documented default |
|---|---|---|
SCD_STRATEGY |
quick, standard, or compact |
quick |
SCD_THREADS |
Parallel threads for SCD | Automatic, based on CPU threads, capped at 4 |
SCD_MATRIX |
Per-theme locale lists, or an empty list to skip a theme | Not set |
SCD_NO_PARENT |
Skip parent theme generation | false |
SCD_COMPRESSION_LEVEL |
Gzip level for static files, 0 to 9 |
6 |
SCD_MAX_EXECUTION_TIME |
Raise the time limit for SCD | Platform maximum of 900 seconds |
SKIP_SCD |
Skip static content deployment in the build stage | Not set |
For build-phase SCD, Adobe’s checklist sets SKIP_SCD to false on build, SCD_STRATEGY to compact, and SKIP_HTML_MINIFICATION to true, then confirms with php ./vendor/bin/ece-tools wizard:ideal-state. SCD_MATRIX is where Cloud projects get most of their time back. An example that deploys the admin in English and skips Luma entirely:
stage:
build:
SCD_STRATEGY: "compact"
SCD_THREADS: 4
SCD_MATRIX:
"Magento/backend":
language:
- en_US
"Magento/luma": [ ]
"Vendor/theme":
language:
- en_US
- fr_CA
If files go missing after a Cloud deploy, particularly custom theme files, Adobe’s guidance is to raise SCD_MAX_EXECUTION_TIME to at least 900 seconds.
Self-hosted pipelines: build once, ship artifacts
Outside Cloud, the same principle applies: build static content once, off the production servers, and ship the result. Adobe documents a path for deploying static files without a database connection: run bin/magento app:config:dump on production, commit the exported configuration, and run static deploy on the build machine. Combine that with an atomic release directory swap and your storefront never serves a half-written pub/static. Adobe specifically warns that custom tools should write client-facing files atomically for this reason.
We walk through the release-directory side of this in zero-downtime Magento deploys with Deployer. Locking dependency versions so every build produces the same output is covered in our piece on Magento 2 Composer and dependency management.
If you run several web nodes, pass the same --content-version to every node’s deploy so signed URLs match and caching keeps working across the cluster.
Troubleshooting slow or broken deploys
| Symptom | Likely cause | Fix |
|---|---|---|
| Deploy builds Luma and Blank you never use | No --theme scoping |
Name themes explicitly or use SCD_MATRIX on Cloud |
| Deploy takes as long on an 8 core runner as a 2 core one | -j left at default 0 |
Set -j to fit available cores and memory |
| Styles missing only after switching to compact | Extension concatenating static URLs, or a known compact bug | Check for ACSD-46815, test with quick, report to the vendor |
| “You need to install the Commerce application” | Running before install, or as the wrong user | Run as file system owner after install, clear pub/static, rerun |
| Hyva storefront unstyled after deploy | Tailwind build skipped or failed before SCD | Run npm run build first and confirm web/css/styles.css exists |
| Old CSS still served after deploy | Browser, Varnish, or CDN cache | Flush cache, purge CDN; confirm deployed version changed |
| Cloud build fails on locales | Locales not in config.php |
Run config:dump and commit, rerun after adding store views |
A sensible default setup
For most single-locale Hyva storefronts, the right answer is simple: build Tailwind in CI, run two scoped static deploy commands with -j and --no-parent, skip LESS and HTML minification for the Hyva theme, and ship the artifact atomically. Strategy choice barely matters with one locale. Add compact when locale count grows and disk usage starts to hurt, after you have checked your extensions build URLs properly.
Multi-store, multi-locale Adobe Commerce builds are where these settings stack up into real minutes per release. If your pipeline is still deploying every theme in every language, our Hyva development services team regularly tightens builds as part of theme and upgrade work, and our broader Magento development services cover Cloud ece-tools configuration and self-hosted pipelines. For the bigger picture of what a Hyva build involves end to end, read what Hyva theme development actually involves.
Bemeir is a Brooklyn ecommerce agency built around Magento, Adobe Commerce, and Hyva, and you can read more about Bemeir and the technology partners we work with. When a platform change is on the table instead, we also build on Shopify, Shopware, and BigCommerce, none of which require a static deploy step at all.
FAQ
Which static content deploy strategy should I use?
If each theme serves one locale, strategy makes no practical difference, so leave the default quick. With several locales per theme, quick is fastest but duplicates shared files, and compact saves the most disk by storing shared files once. Test compact first, because extensions that concatenate static URLs can break under it.
How many parallel jobs should I pass to -j?
The default is 0, which means no parallelism. Start with the number of CPU cores on your build machine and lower it if the runner runs short of memory, since each job is a separate PHP process. On Adobe Commerce Cloud, SCD_THREADS defaults to an automatic value capped at 4.
Do I still need static content deploy on a Hyva theme?
Yes. Production mode still requires every static file to exist in pub/static. Hyva just removes most of the expensive work, so you can skip LESS compilation, JavaScript bundling, and HTML minification for the Hyva theme, and build the Tailwind stylesheet with npm run build before running the deploy.
Why does static content deploy refuse to run in developer mode?
In default and developer mode Magento generates static files on demand, so the command only runs there if you add -f or --force. In production mode it runs without the flag, because files are not generated on request.
Can I run static content deploy without a database?
Yes. Export configuration with bin/magento app:config:dump on production, commit the resulting files, and run the deploy on a separate build machine. Adobe Commerce Cloud’s build-phase deployment relies on the same idea, which is why you must re-run config:dump after adding store views.





