Technology

Blue-Green Deployment for WooCommerce and Laravel

Blue-Green deployment separates preparation of a new application release from the version currently serving users. For WooCommerce and Laravel, that can reduce the risk of partial file updates, broken checkouts and deployment errors. On a VPS, the available permissions and capacity determine how you can manage the web server, PHP, queues and database. Switching traffic back is safe only while the old release remains compatible with shared data and queued work; it does not undo orders, payments or other writes.

In this article we will focus specifically on WooCommerce (WordPress + PHP) and Laravel apps running on VPS and cloud hosting. We will look at concrete architecture patterns, how to handle the database, sessions, queues and file uploads, and what changes when you have only one VPS versus multiple servers. The patterns below are design options to adapt to your application’s state, release process and available server capacity.

Why Blue-Green Deployments Matter for WooCommerce and Laravel

Blue-green deployment is a release strategy where you keep two application versions ready to serve traffic, either on separate infrastructure or sharing infrastructure and state:

  • Blue: the current production version
  • Green: the new version you are preparing to switch to

Normally one version receives production traffic. After validating green, you change routing to send new traffic there (through Nginx, a load balancer or DNS). In-flight requests and cached DNS answers can keep blue active during the transition. You can route traffic back if blue still supports the current shared state.

For WooCommerce and Laravel on VPS or cloud hosting, this matters because:

  • E‑commerce checkouts must not break: A partial deployment during a payment attempt can create inconsistent orders, abandoned carts and support tickets.
  • Schema changes are risky: Both WooCommerce and Laravel apps often require database migrations. Blue‑green requires schema changes to remain compatible with both code versions during the transition and rollback window.
  • Queues, cron and workers may remain active during deployment: If you just overwrite files in-place, workers may crash mid-job or run mixed code versions.
  • VPS and cloud servers are flexible: You are not locked into a panel-based “single click publish”; you can design a repeatable, testable deployment flow.

If you are already thinking about dev / staging / production separation, our article on hosting architecture for dev, staging and production fits nicely as the wider workflow around the blue‑green ideas we will cover here.

The Core Concept: What Blue-Green Deployment Actually Is

The basic Blue-Green sequence:

  1. Run two environments (blue and green) that are as similar as possible.
  2. Send all production traffic to only one of them (say blue).
  3. Prepare and test your new version on the other (green). Use isolated data and sandbox integrations for write tests; keep checks against shared production data non-destructive.
  4. Switch new traffic to green, allowing for requests or connections still using blue.
  5. If needed, switch back while blue remains compatible with shared data and queued work.

In practice, you implement this in different layers depending on your infrastructure:

  • Application layer: Two release directories and a web root reached through current -> releases/blue or releases/green.
  • Proxy layer: A load balancer or reverse proxy selects the active application pool.
  • DNS or edge layer: Blue and Green use separate origins; DNS answers or CDN origin routing determine which receives new requests. This is routing, not necessarily an HTTP redirect.

The big advantage is that much of the preparation happens before cutover. Dependency installation, asset builds and release-local configuration can be prepared while users use blue. Migrations and shared-cache changes need separate compatibility planning because they can affect blue immediately. The routing change can be small, but traffic draining and DNS caching can extend the transition.

Blue-Green Architecture Options on VPS and Cloud Hosting

On VPS and cloud hosting you usually have one of these situations:

  • Single VPS running web server, PHP-FPM and database
  • Single VPS for application + managed or separate database instance
  • Multiple VPS / virtual machines behind a load balancer or reverse proxy

Blue-green is possible in all three, but the implementation details are different.

Option 1: Single VPS with Blue/Green Release Directories

This is a simple starting point for code releases, but both versions still share the VPS and its failure risks.

Typical structure:

/var/www/myapp/
  current -> releases/blue
  releases/
    blue/
    green/
  shared/
    uploads/    # WordPress media, when used
    app-data/   # persistent Laravel application files
    .env        # Laravel production environment

If the application’s public entry directory is public, your Nginx document root points to /var/www/myapp/current/public. Otherwise, use the actual public entry directory; do not assume this layout applies unchanged to every WooCommerce installation. During deployment you:

  1. Prepare a new, empty release directory from a reviewed commit and lock files. Supply the target environment and persistent storage before Composer scripts or Artisan commands run.
  2. Build release-local Laravel config, route and view caches. Plan PHP-FPM/OPcache behavior separately; WordPress object-cache warmup across requests requires a persistent backend integration.
  3. Apply only approved database changes compatible with Blue and Green; additive changes still need lock and workload testing. Defer destructive changes beyond the rollback window.
  4. After isolated regression tests and non-destructive production-readiness checks pass, coordinate workers and replace the current symlink using the same-filesystem method below.
  5. Verify the actual served release, drain old requests, invalidate selected caches and monitor errors. Reload services only as required by their configuration.

This avoids adding a second application server, provided the VPS has enough CPU, memory and disk space for both releases and deployment work alongside live traffic.

For a script-level example, see our guide to CI/CD to a VPS with rsync, symlinks and systemd.

Option 2: Two VPS Nodes Behind a Load Balancer or Reverse Proxy

If you already run multiple application servers, you can take blue-green one level up:

  • Blue environment: one or more app servers running the current code
  • Green environment: another set of app servers running the new code; when sharing a database, both versions must support its live schema

You then use a load balancer or Nginx reverse proxy to route all live traffic to either blue or green upstreams. For example, this minimal Nginx HTTP routing fragment belongs inside the http context; it is not a complete production HTTPS configuration:

upstream app_blue {
    server 10.0.0.10;
}

upstream app_green {
    server 10.0.0.20;
}

server {
    listen 80;
    server_name example.com;

    # set belongs in server context, not directly in http
    set $active_upstream app_blue;

    location / {
        proxy_set_header Host $host;
        proxy_pass http://$active_upstream;
    }
}

Change $active_upstream to app_green, validate the complete configuration with nginx -t, then use the configured graceful reload. Keep Blue available while existing requests drain. This HTTP routing fragment does not configure HTTPS, trusted proxy headers, active health checks or weighted traffic splitting; add those to the deployment design as required. The Host header preserves the public hostname for the backend virtual host. For a separate traffic-splitting design, see canary deployments on a VPS with Nginx weighted routing.

Option 3: DNS / Edge-Based Blue-Green

In some setups you don’t control the internal network but can point DNS or a CDN/WAF to different origins. Then your blue-green looks like:

  • blue-origin.example.com → current production
  • green-origin.example.com → new version
  • CDN/WAF or DNS configuration decides which origin serves www.example.com

This pattern works well when you already use a CDN or WAF in front of your VPS servers and want to hide origin changes behind a single public hostname. If you change public DNS records, lower their TTLs far enough in advance for previously cached answers to expire. DNS cutover and rollback are not atomic: keep both origins usable while caches and existing connections drain. If only a CDN’s origin routing changes and public DNS stays the same, lowering public DNS TTLs does not control that transition. Our TTL planning for migrations explains this in detail.

Blue-Green for WooCommerce: Database, Sessions and Media

WooCommerce is stateful in many ways: shopping carts, orders, user accounts, coupons, background jobs, inventory… much of that state is database-backed. That makes blue‑green more sensitive than a simple static website. Let’s break it down.

Single Shared Database for Blue and Green

A straightforward WooCommerce blue-green design on a VPS or cloud server uses one primary database shared by both application environments. In that case:

  • The shared database has one current schema; two application directories do not isolate schema changes.
  • Both releases need compatible read and write behavior throughout cutover and rollback. A read-only window alone does not make incompatible code safe: plan maintenance, affected background work and recovery when compatibility cannot be preserved.
  • Both production releases must reach the intended database with appropriate privileges. Their credential strings need not be identical.

A controlled WooCommerce update separates validation from shared-production changes:

  1. Build and test Green against an isolated database and media copy. Disable production payments, email, webhooks and scheduled side effects; use sandbox integrations for checkout tests.
  2. Test the exact WooCommerce, plugin and theme update path, including database upgrades. Do not assume an automatic plugin migration is additive or compatible with Blue.
  3. Prepare the validated code for the current live database, media and production integration settings. Never overwrite live data with the test copy: new orders may have arrived while tests ran.
  4. Run only the approved compatible production migration plan once. Check Green non-destructively against current state; then switch new traffic and coordinate background tasks.
  5. Retain Blue and the compatible schema through the rollback window. Remove obsolete structures only in a later, separately planned change.

For larger tables, see MySQL schema migrations with Blue-Green, gh-ost and pt-online-schema-change. Online schema tools have engine, topology and operation requirements; they do not make every migration non-blocking or reversible.

Sessions, Carts and Caching

When you have two application versions (blue and green) with a shared database, you must think about:

  • WooCommerce sessions and any additional plugin/PHP session mechanism.
  • Persistent object cache when configured, plus page and CDN caches.
  • Authentication cookies, keys and salts, including consistent hostname and cookie settings.

A few practical rules:

  • The standard WooCommerce session handler uses its database session table and cache. Keep Blue and Green on compatible session state and cookie settings; installing Redis object caching does not automatically migrate plugin or PHP sessions.
  • Preserve WordPress authentication keys and salts across the two production releases. A deliberate key rotation invalidates cookies and should be planned separately.
  • Invalidate selected release-dependent page/cache entries without clearing session, queue or lock data. Exclude carts, checkout, account and other personalized responses from shared page caching. Retain old versioned assets while cached pages or in-flight requests still reference them.

For deeper guidance on cache layers around WooCommerce (object cache, Redis/Memcached, page cache), our article on WordPress object cache with Redis or Memcached is a good complement to this blue‑green strategy.

Uploads and Media

A standard WooCommerce installation keeps uploaded media under wp-content/uploads; verify customized paths and any media-offload plugin:

  • Use shared production uploads reachable from both releases, with the intended ownership and permissions.
  • Keep write tests on a separate media copy. Confirm that uploads arriving during preparation remain available after cutover.
  • Exclude shared data from release cleanup and destructive synchronization. For object storage, make both production releases use compatible bucket, path and URL settings through the configured media integration.

Offloading media to object storage can simplify blue‑green even more because all app versions see the same media URL structure. Our guide on S3/MinIO media offload for WordPress and WooCommerce walks through designs that pair nicely with blue‑green deployments.

Blue-Green for Laravel: Queues, Horizon and Migrations

Laravel tends to be more explicit about deployment flows than WordPress/WooCommerce, but blue-green still requires careful thinking around queues, cache and database migrations.

Persistent State and Shared Backends

Laravel is not automatically stateless at the file level. Inventory the application’s configured storage, including:

  • The database, session store, queue backend and application cache.
  • Uploaded and private files, which may use local storage/app paths or external storage.
  • Logs, file sessions and compiled views, depending on configuration. Persistent data and release-generated caches have different lifecycles.

Separate persistent state from the release before selecting shared backends:

  • Configure the intended production database, sessions and queue backends consistently. Keep APP_KEY and cookie settings compatible across releases; do not use a staging key in production.
  • Retain persistent application files and any file sessions across cutover. Make storage and bootstrap/cache writable by the processes that require them.
  • Keep bootstrap/cache and compiled views release-local. If sharing all of storage, configure a separate writable VIEW_COMPILED_PATH for each release before building config/view caches.
  • For the simple handover below, designate one worker pool and one scheduler owner, with explicit process-manager coordination.

Handling Queues and Horizon

Queues are where many Laravel blue‑green deployments go wrong. Problems usually happen when:

  • Old workers cannot deserialize or process jobs produced by new code, or new workers cannot handle jobs left by Blue.
  • Two independently configured schedulers enqueue the same work twice.
  • A process manager automatically restarts Blue after a termination signal, or launches workers from the wrong release. Multiple workers alone do not imply duplicate execution, but retries and job side effects still need idempotency.

To avoid this:

  1. Prepare Green, its environment and release-local caches before pausing queue consumption. Test job payload compatibility in both directions for the rollback window.
  2. Coordinate the process manager so Blue stops taking new jobs, finishes current work and does not automatically restart from the old release. php artisan queue:restart requests exit after the current job; php artisan horizon:terminate is used with a monitor that restarts Horizon. Neither is a persistent stop lock. Verify the cache used for restart signals and allow sufficient shutdown time.
  3. Switch web routing, then start the selected worker pool or Horizon with the Green release’s command path and working directory. Old web requests may still enqueue work; a pause can increase queue latency.
  4. Use one scheduler owner in this model. Point cron to the active release; for sub-minute schedule:run loops, invoke php artisan schedule:interrupt after deployment. Separately track jobs already launched by the scheduler.
  5. Monitor failed jobs and backlog. Roll back workers and web traffic only if Blue supports the current data and queued payloads. Do not purge the queue as a release step.

Our in‑depth guide on background jobs and queue management on a VPS covers systemd/Supervisor examples.

Laravel Migrations in a Blue-Green World

Laravel migrations are simple on paper but can be dangerous in busy production systems, especially when they lock large tables. When you combine them with blue‑green:

  • Test backward-compatible schema and data changes against both releases. Adding a column does not itself prove that a migration is non-blocking.
  • Measure lock duration and workload effects for the actual database engine and version; evaluate online tools against their supported operations.
  • Expand the schema, deploy compatible code, complete any staged data transition, and only remove old structures after Blue has drained and the rollback window closes.

Replication and failover are separate parts of an availability design; two code releases do not provide database redundancy. For a deeper dive on replication and failover, our article on MySQL and PostgreSQL replication on VPS for high availability is a useful next read.

Laravel-Specific Deployment Steps

In a typical blue‑green deployment for Laravel on a VPS or cloud instance, the green release does roughly this:

  1. Create a fresh release from a reviewed commit and lock files; do not copy generated config/cache files from an older release.
  2. Before Composer or Artisan runs, supply the final environment and persistent file/session paths. Prepare writable storage and release-local cache/view directories. Composer can run application scripts during install, so review their side effects.
  3. Run composer install --no-dev --optimize-autoloader from the release directory. Build frontend assets with locked dependencies, or supply the previously tested build.
  4. Run php artisan config:cache, php artisan route:cache and php artisan view:cache; stop on failure. After config is cached, editing .env alone is insufficient: regenerate the cache.
  5. Use isolated data and integrations for write tests. Apply the approved compatible production migration plan once; php artisan migrate --force bypasses the production confirmation, not compatibility checks.
  6. Run non-destructive readiness checks against the intended live backends, coordinate workers and the scheduler, then switch traffic and monitor. The command behavior here follows Laravel 12; verify the release you operate.

For the surrounding server setup, see deploying Laravel on a VPS with Nginx, PHP-FPM and queues.

Step-by-Step Example: Blue-Green on a Single VPS

The release-directory pattern can serve either stack, but their document roots, writable paths and PHP routing differ. The following Nginx example is specifically for Laravel.

1. Directory Layout

Example release layout; Blue is initially active:

/var/www/project/
  current -> releases/2024-12-20_0900
  releases/
    2024-12-20_0900/    # blue
    2025-01-01_1500/    # green, prepared separately
  shared/
    uploads/            # production WordPress media, if used
    app-data/           # persistent Laravel files
    .env                # Laravel environment

For WooCommerce, connect the release’s wp-content/uploads to production media and preserve its intended wp-config.php settings. For Laravel, connect persistent disk/session paths and supply .env before preparation commands. Keep generated caches and compiled views isolated per release. If using the local public disk, prepare the public/storage link to its configured target.

2. Nginx Virtual Host

This Laravel HTTP example belongs inside Nginx’s http context. The public directory is current/public; never expose the Laravel project root. Verify the PHP-FPM socket and included FastCGI parameters on your system, and merge this into the site’s actual HTTPS configuration. Standard WordPress normally serves its installation root and needs WordPress-specific PHP rules; do not paste this Laravel-only routing into WooCommerce unchanged.

server {
    listen 80;
    server_name example.com;
    root /var/www/project/current/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /index.php {
        fastcgi_pass unix:/run/php/php-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root/index.php;
        include fastcgi_params;
    }

    location ~* \.php$ {
        return 404;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

The case-insensitive PHP filename rule returns 404 for other PHP files; only the exact front-controller path is sent to PHP-FPM. $realpath_root resolves the root’s symbolic links for the current request. It helps pass a resolved release path to PHP; it does not make every later file read across a deployment atomic. Check the served release, PHP-FPM/OPcache behavior and old-asset retention. Validate Nginx configuration before reload, and retain Blue until old requests and jobs finish.

3. Deployment Script (Simplified)

Serialize deployments with a deploy lock. On Linux with GNU coreutils, keep the temporary and active links in the same directory on a local filesystem supporting atomic rename. Require current to be an existing symlink and current.next to be absent:

  1. Prepare and test Green, final environment, persistent storage, caches and the approved migration plan as described above.
  2. Coordinate workers and scheduled tasks, then replace the link:
    test -L /var/www/project/current &&
    test -d /var/www/project/releases/2025-01-01_1500 &&
    ln -sT /var/www/project/releases/2025-01-01_1500 /var/www/project/current.next &&
    mv -Tf /var/www/project/current.next /var/www/project/current

    The temporary link and current are in the same parent directory. GNU mv -T treats the destination as the link to replace rather than a directory to move into. Same-filesystem rename replaces that directory entry without an absent-link interval. Stop if a step fails and inspect a leftover temporary link; do not blindly overwrite it.

  3. Confirm the active release, complete the process-manager handover and invalidate selected caches. Reload services only where required; do not clear shared sessions, queues or locks.
  4. Observe application and business metrics. Keep Blue and its assets while requests drain and rollback remains allowed. Atomic link replacement does not provide an atomic database, worker or request transition.

With systemd and a CI system (GitHub Actions, GitLab CI, etc.) you can automate all of this. We show a full example CI pipeline in our post on deployments to a VPS with GitHub Actions.

4. Rollback

A retained release can make code rollback quick, provided it still supports current data, files, sessions, cache formats and queued work:

  1. Select the previous compatible release and coordinate Green workers and scheduler ownership.
  2. Create an unused temporary symlink to Blue and replace current using the same-filesystem rename procedure.
  3. Point process-manager paths to Blue, resume its workers, handle selected release caches and verify the served version and live metrics. Keep in-flight Green requests and their potential writes in the recovery plan.

Routing rollback does not reverse database writes or payment-provider actions. A backup restore can discard orders and other changes since the recovery point, so data recovery needs a separate runbook, a tested restore and reconciliation of external transactions. Do not automatically restore an old database merely because code rollback was requested.

See the Linux rename documentation for the filesystem guarantee and the official Laravel deployment guide for application preparation.

Operational Considerations

Monitoring and Health Checks

Validate readiness and observe the whole transition:

  • Use a minimal application readiness endpoint that tests the dependencies required to serve requests and exposes no secrets or customer data. An HTTP 200 response alone does not prove checkout or queue health.
  • Verify that the check reaches Green, with the intended hostname, HTTPS and routing. A hosts-file entry selects an IP, not a directory on the same IP; a single-VPS test needs a separate restricted virtual host or equivalent route.
  • Exercise carts, sandbox payments, login and notifications on isolated data. Keep checks against the live shared database non-destructive.
  • Compare error rates, response times, queue age, failed jobs, orders and resource use over a defined observation window. Gate automatic rollback on demonstrated state compatibility.

If you do not have monitoring yet, our guide on VPS monitoring and alerts with Prometheus, Grafana and Uptime Kuma is a solid starting point.

Backups and Disaster Recovery

Blue-green deployment is not a substitute for backups. Schema mistakes, buggy migrations or application logic errors can corrupt data just as quickly on blue or green. Always:

  • Schedule regular full database backups and test restoring them.
  • Use off‑site storage for backups (object storage, remote VPS, or colocation backup node).
  • Document a simple recovery runbook so your team knows exactly what to do.

For recovery design, see ransomware-resistant hosting backup strategies. Retained code releases complement independently protected data backups and restore drills.

When Blue-Green Might Be Overkill

Not every site needs a full blue-green setup from day one. For example:

  • Small WooCommerce stores with low traffic and off‑peak maintenance windows.
  • Early‑stage Laravel projects with a few users and simple schemas.
  • Internal tools where a short maintenance page is acceptable.

As the cost of a failed release grows, compare Blue-Green’s extra storage, preparation and operational work with planned maintenance or other rollout methods. A single-VPS release layout can be a starting point if it has sufficient headroom; it still shares that server’s failure risks. Multi-server or canary designs require their own routing and state checks.

How dchost.com Fits Into Your Blue-Green Strategy

A dedicated server or VPS with the necessary administrative access can provide the controls needed for a custom release workflow. Match DCHost service options to the permissions, capacity and operational responsibilities your design requires:

  • Release directories and protected persistent storage.
  • Control over Nginx/Apache, PHP-FPM and process-manager configuration.
  • CI/CD access, health checks, monitoring and tested backups.
  • Capacity for both releases during preparation, or separate application nodes and a routing layer when needed.

Size CPU, RAM, disk space and I/O for live traffic plus deployment work. Document which services you operate, where persistent data lives and what happens if the shared server or database fails. A second application release alone does not establish high availability.

Start with a deployment and recovery diagram: the two releases, shared state, traffic switch, worker and scheduler owners, readiness gates and rollback conditions. Rehearse the complete sequence with representative data before applying it to the production store or application.

Frequently Asked Questions

Blue-Green keeps the current and next application releases separate during preparation, then routes new traffic to the validated version. It can reduce partial-update risk for WooCommerce and Laravel. Shared databases, sessions, media and queued jobs still need compatibility testing. Existing requests may continue on Blue; switching back does not reverse orders, payments or migrations.

Yes, if the VPS has adequate capacity and you control the web root, filesystem and relevant processes. Use fresh release directories and a current symlink; create a temporary symlink beside it, then replace current with a same-filesystem rename such as GNU mv -T. A direct ln -sfn command is not a sufficient atomicity guarantee. Laravel serves current/public; use the actual WordPress public root for WooCommerce. Retain old requests, assets and state compatibility.

Test the exact migration against both releases and the actual engine and workload. In a shared-database model, a change started from Green also affects Blue. Prefer compatible expansion, then deploy code, and remove old structures only after the rollback window closes. Additive and online operations can still have locks or restrictions. Use isolated data for write tests; never restore the staging database over current orders.

Prepare Green first, then coordinate the process manager so Blue finishes current jobs and does not restart from its old path. queue:restart and horizon:terminate are exit/restart signals, not persistent stop locks. Route traffic and start the intended Green workers, preserving compatible queued payloads and allowing for jobs from in-flight Blue requests. Keep scheduler ownership explicit; roll back only while Blue can process current data and jobs.

For a small store, early application or internal tool with an acceptable maintenance window, tested backups and a rehearsed maintenance deployment may be enough. Blue-Green is useful when the business cost of release errors justifies the extra preparation, capacity and operational work. A single-VPS layout can be a starting point, but it shares server failure risks and does not guarantee zero downtime.
↑