Zero-Downtime Deployments for Magento 2

Zero-Downtime Deployments for Magento 2

November 19, 2025 · By Magento Company
Zero-Downtime Deployments for Magento 2

Taking a Magento store offline to deploy is a choice, not a requirement. Zero-downtime deployment is achievable with standard tooling - but Magento has specific traps (setup:upgrade, static content, cache warming) that generic deploy guides miss. Here is the pattern that works.

The foundation is release directories with an atomic symlink switch (Capistrano-style, or Deployer, or Envoyer):

/var/www/releases/20260928-1430/
/var/www/releases/20260928-1915/
/var/www/current -> releases/20260928-1915

Deploy steps: build the new release directory completely, run its commands, then flip the current symlink - an atomic operation measured in milliseconds. Rollback is flipping the symlink back. Shared paths (var/, pub/media, app/etc/env.php) are symlinked into each release from a shared directory so uploads and config survive.

The setup:upgrade Problem

bin/magento setup:upgrade runs schema and data changes and, naively run, either needs maintenance mode (downtime) or risks running mid-traffic against old code. The honest options:

  • No schema change deploys: when the release has no db_schema.xml or patch changes, skip setup:upgrade entirely (check setup_module versions). Most deploys should be this kind
  • Schema changes: run setup:upgrade immediately before the symlink flip, on the new release, accepting a few seconds of risk window - Magento schema changes are usually backward-compatible additions (new tables, new columns), which old code tolerates for the seconds involved
  • Breaking schema changes: these genuinely need maintenance mode. Design them away where possible (add-then-migrate-then-drop across two releases); where not possible, be honest and take the two-minute window at 4am

Static Content and Cache

  • Generate static content in CI (as part of the build artifact) or during release preparation, never lazily after flip - first-hit compilation is your downtime
  • Flush caches deliberately, not reflexively: config changes need config cache flush; layout changes need layout/block_html. Blanket cache:flush on every deploy empties FPC and makes the next minutes slow for everyone
  • Warm the cache after flip: crawl the top pages (homepage, top categories, top products) with a script before announcing done. A cold FPC after deploy is self-inflicted slowness

Varnish and CDN

Purge by tag, not full ban: Magento’s Varnish integration purges specific content on change. On deploy, a full purge is sometimes honest (theme changed everything) but on most deploys targeted purging keeps hit ratios high. With Fastly (Commerce Cloud) the same logic applies through its purging API.

The Checklist

  1. Build artifact in CI, deployed to a new release directory
  2. Schema change? If yes, run setup:upgrade pre-flip (or maintenance mode for breaking changes)
  3. Flip symlink
  4. Targeted cache flush, queue consumer restart (they hold old code in memory - easy to forget)
  5. Cache warm + smoke test
  6. Rollback = symlink back + restore pre-deploy DB backup if schema moved

Zero downtime is a discipline, not a tool: artifact builds, atomic switches, honest handling of schema changes. Get those right and “deployment” stops appearing in anyone’s risk register.

DevOps Operations Magento 2