switching instead of worrying, with zero downtime
Blue green deployment replaces the risky, gradual rollout with a single, instantly reversible cut: two fully identical environments run in parallel, the load balancer points at one while the new version is fully prepared and tested in the other. This article shows how blue green deployment for Symfony is built in practice, including database, sessions and rollback.
Table of Contents
- 1. What blue green deployment means for Symfony in practice
- 2. Building two identical environments: blue and green
- 3. Traffic switching at the load balancer or reverse proxy
- 4. The database challenge in blue green deployment
- 5. Sharing sessions and cache between blue and green
- 6. Asset versioning and cache invalidation during the switch
- 7. Automated smoke tests before switching
- 8. Rollback strategy: instantly back to the old environment
- 9. Blue green deployment versus rolling update and canary
- 10. Summary
- 11. FAQ
1. What blue green deployment means for Symfony in practice
Blue green deployment is a deployment strategy where two fully identical production environments exist in parallel, usually called blue and green. At any given time, only one of the two environments serves real user traffic, while the other is either inactive or currently receiving the new application version. Switching between the two happens through a single configuration change at the load balancer, not through gradually replacing individual servers.
The decisive difference from a classic rolling update lies in the atomicity of the switch. In a rolling update, the old and new versions run simultaneously on different servers for a while, which can cause inconsistencies with incompatible changes. With blue green deployment, at any point in time either the entirely old or the entirely new version serves all traffic, never a mix of both. This significantly simplifies testing, because the new version can be fully verified under production conditions in the inactive environment before a single real user ever sees it.
For a Symfony application, blue green deployment means concretely: two complete sets of application servers that share the same cache, the same session infrastructure and the same database, but can run different code versions. The real challenge lies not in copying the servers, but in cleanly handling the shared, stateful resources, which the following sections cover in detail.
2. Building two identical environments: blue and green
The basic requirement for working blue green deployment is genuine identity between both environments: same PHP version, same extensions, same server resources, same network configuration. Any deviation between blue and green undermines the promise that a successful test in the inactive environment actually predicts behavior in production. In practice, this identity is achieved most reliably through infrastructure as code, where both environments are created from the same Terraform or Ansible definition, parameterized only by the environment name.
A common mistake is treating blue as the permanently productive environment and only sporadically spinning up green for deployments. Over time, this causes green to drift unnoticed from blue, for example through manually installed security updates applied to only one side. Robust blue green deployment treats both environments as equal and rotates the active/inactive role with every release, so drift caused by missing symmetry surfaces quickly.
#!/usr/bin/env bash
# provision-environment.sh — build the inactive environment identically
# to the currently active one, using the same infrastructure definition
set -euo pipefail
TARGET_ENV="${1:?Usage: provision-environment.sh <blue|green>}"
RELEASE_TAG="${2:?Usage: provision-environment.sh <env> <release-tag>}"
echo "[INFO] Provisioning ${TARGET_ENV} with release ${RELEASE_TAG}"
terraform -chdir="infra/${TARGET_ENV}" apply \
-var="release_tag=${RELEASE_TAG}" \
-var="environment=${TARGET_ENV}" \
-auto-approve
ansible-playbook -i "inventory/${TARGET_ENV}.ini" deploy.yml \
--extra-vars "release_tag=${RELEASE_TAG}"
echo "[OK] ${TARGET_ENV} provisioned and ready for smoke tests"
3. Traffic switching at the load balancer or reverse proxy
The actual switching moment in blue green deployment happens at the load balancer or reverse proxy, not inside the application itself. Nginx, HAProxy or a cloud load balancer receive a new upstream configuration that now points at green instead of blue, or the other way around. This step should complete in under a second and must not abruptly drop existing connections, which is why a graceful reload rather than a hard restart of the proxy is required.
With DNS based blue green deployment, the TTL of the DNS record also needs attention. A TTL of one hour means some clients will keep addressing the old environment for up to an hour even after the DNS record was changed. For true zero downtime switching, a layer 7 proxy with immediate configuration changes is clearly preferable to a DNS change, since the proxy performs the switch without client side cache delay.
# /etc/nginx/conf.d/symfony-upstream.conf
# The active environment is selected via a single upstream block.
# Switching blue/green means reloading this file with the new target.
upstream symfony_active {
server 10.0.1.10:9000 max_fails=2 fail_timeout=10s; # green environment
# server 10.0.2.10:9000 max_fails=2 fail_timeout=10s; # blue environment
}
server {
listen 443 ssl http2;
server_name app.mironsoft.de;
location / {
fastcgi_pass symfony_active;
include fastcgi_params;
}
}
# switch-traffic.sh reloads nginx after rewriting the upstream target:
# nginx -t && nginx -s reload
4. The database challenge in blue green deployment
The database is the point where blue green deployment turns from a pure infrastructure topic into a genuine application design problem. Both environments typically access the same database, meaning the database schema must be compatible with both the old and the new application version at the same time. A migration that renames or drops a column immediately breaks the old version as long as it is still running in parallel.
The solution is the expand contract pattern: new columns are added alongside existing ones, existing columns are never removed immediately. Both application versions can either ignore or use the new column, depending on the code state. Only in a later, separate deployment, once the old version is finally decommissioned, are the no longer needed columns removed. For blue green deployment with Symfony and Doctrine, this means splitting every schema change into at least two separate, backward compatible migration steps instead of performing it in a single step.
5. Sharing sessions and cache between blue and green
If each environment used its own local session storage, every switch would lose all active user sessions, because green would not know about blue's sessions. For seamless blue green deployment, sessions must therefore live in an external store shared by both environments, typically Redis. Symfony supports this natively through the RedisSessionHandler, so a user in the middle of a checkout process does not even notice the switching moment.
The same applies to the application cache. If the Symfony cache runs locally on each instance's filesystem, two separate, potentially inconsistent cache states arise between blue and green. A shared Redis or Memcached cache ensures both environments see consistent data, regardless of which code version is currently active. This shared infrastructure is, alongside the database, the second load bearing pillar without which blue green deployment does not work in practice.
# config/packages/framework.yaml — shared Redis session storage
# so a user session survives a blue/green traffic switch
framework:
session:
handler_id: 'redis://redis.internal.mironsoft.de:6379'
cookie_secure: auto
cookie_samesite: lax
gc_maxlifetime: 3600
cache:
app: cache.adapter.redis
default_redis_provider: 'redis://redis.internal.mironsoft.de:6379'
6. Asset versioning and cache invalidation during the switch
Static assets such as CSS and JavaScript files in Symfony are usually given a version hash in the filename, so browser caches are automatically invalidated when the content changes. With blue green deployment, it is important that both the old and the new version keep their respective asset files reachable under a stable URL at the same time, for example through a content delivery network that serves both version states in parallel instead of deleting old assets immediately.
A user who loaded an HTML page from the old version shortly before the switch will keep requesting the old asset paths afterward. If these are deleted the moment green becomes active, that user receives broken stylesheets or malfunctioning JavaScript. For clean blue green deployment, old assets should therefore remain reachable alongside the new ones for a defined transition period, usually several hours, before being finally removed.
#!/usr/bin/env bash
# publish-assets.sh — keep both blue and green asset versions available
# on the CDN during the transition window
set -euo pipefail
RELEASE_TAG="${1:?Usage: publish-assets.sh <release-tag>}"
CDN_BUCKET="s3://mironsoft-assets/releases"
aws s3 sync "public/build/" "${CDN_BUCKET}/${RELEASE_TAG}/" \
--cache-control "public, max-age=31536000, immutable"
echo "[OK] Assets for ${RELEASE_TAG} published, previous releases remain live"
# Cleanup of releases older than 24h runs as a separate, scheduled job
7. Automated smoke tests before switching
The biggest advantage of blue green deployment is lost if the inactive environment goes live untested. Before every traffic switch, an automated smoke test suite should run against the new environment, reachable through an internal access path without any real user traffic involved. These tests typically check critical paths: login, checkout, central API endpoints and the health check route.
If even a single smoke test fails, a well configured blue green deployment must not allow the switching process to start at all. This safeguard is far cheaper than a rollback after a failed switch, since not a single real user was affected yet. The smoke test suite should therefore be part of the CI pipeline and run automatically against the freshly provisioned, inactive environment before the switch is even cleared for execution.
#!/usr/bin/env bash
# smoke-test.sh — run critical path checks against the inactive environment
# before allowing the traffic switch to proceed
set -euo pipefail
TARGET_URL="${1:?Usage: smoke-test.sh <internal-url>}"
FAILURES=0
check() {
local path="$1" expected="$2"
local code
code=$(curl -s -o /dev/null -w "%{http_code}" "${TARGET_URL}${path}")
if [[ "$code" != "$expected" ]]; then
echo "[FAIL] ${path} returned ${code}, expected ${expected}" >&2
FAILURES=$((FAILURES + 1))
else
echo "[OK] ${path}"
fi
}
check "/health/ready" "200"
check "/login" "200"
check "/api/v1/products?limit=1" "200"
check "/checkout" "200"
if (( FAILURES > 0 )); then
echo "[ABORT] ${FAILURES} smoke test(s) failed — switch cancelled" >&2
exit 1
fi
echo "[OK] All smoke tests passed — safe to switch traffic"
8. Rollback strategy: instantly back to the old environment
The main practical advantage of blue green deployment shows up in an emergency: a rollback does not mean reverting code or redeploying an old version, but simply switching the load balancer back to the previous environment, which kept running unchanged the whole time. This rollback takes exactly as long as the original switch, usually under a second, making it orders of magnitude faster than a classic redeployment.
It is important not to shut down the old environment immediately after a switch, but to leave it active in standby for a defined observation period, often thirty minutes to several hours. Only once monitoring and error rates of the new environment remain stable over that period is the old environment actually released or reused for the next release. This standby phase is the real safety benefit blue green deployment offers over deployment strategies without a parallel second environment.
9. Blue green deployment versus rolling update and canary
The table below compares blue green deployment against the two other common deployment strategies.
| Strategy | Rollback speed | Infrastructure cost | Risk of mixed versions |
|---|---|---|---|
| Rolling update | slow, gradual | low, no second environment | high, old and new version active in parallel |
| Canary release | medium, staged withdrawal | medium, small extra capacity | medium, controlled partial traffic |
| Blue green deployment | instant, one configuration change | high, duplicated infrastructure | none, never mixed versions |
The higher infrastructure cost of blue green deployment is the price for an instant rollback and the guarantee of never having two versions under real traffic at the same time. For applications with high risk from faulty deployments, such as the checkout area of a shop, this safety benefit clearly outweighs the additional cost in most cases.
Mironsoft
Symfony DevOps, deployment infrastructure and zero downtime strategies
Setting up blue green deployment for your Symfony operations?
We set up blue green deployment for Symfony: shared session and cache infrastructure, expand contract migrations, smoke tests and a rollback in seconds.
Infrastructure setup
Building two identical environments with a shared session and cache layer
Migration strategy
Migrating Doctrine migrations to the expand contract pattern for parallel versions
Switch automation
Integrating smoke tests and traffic switching into your existing deployment pipeline
10. Summary
Blue green deployment for Symfony replaces the anxious watch over a running rolling update with a controlled, instantly reversible switching moment. Two identical environments, shared session and cache infrastructure through Redis, and a database schema that grows following the expand contract pattern form the technical foundation. The actual switch at the load balancer takes under a second and never involves a mix of old and new versions.
Automated smoke tests before switching prevent untested code from going live at all, while a standby phase for the old environment enables a rollback at the same speed as the original switch. The higher infrastructure cost of blue green deployment pays off for applications with high risk from deployment failures, through drastically reduced downtime and a noticeably greater sense of safety with every release.
Blue Green Deployment for Symfony — The Essentials at a Glance
Identical environments
Create blue and green from the same infrastructure as code definition, rotate roles with every release.
Shared resources
Sessions and cache shared through Redis, database following the expand contract pattern for parallel compatibility.
Instant switch
One configuration change at the load balancer, under a second, never mixing versions.
Fast rollback
Old environment stays active in standby, rollback is just another switch, not a redeployment.