BitBootcampBitBootcamp ← all explainers 🔄 Review ⚙ Settings

Pattern — Blue-Green Deploy

The problem it solves

The same mistake shows up at two scales: a big-bang weekend cutover wipes the old system on Tuesday and leaves nothing to roll back to (Drill 54), and a "tidy" release welds a destructive schema drop onto the app deploy so the previous version can't even boot (Drill 57). The common shape: the release destroys the very thing its own rollback depends on. By the time the bug surfaces — hours later — the way back is already gone, and the team fixes forward under fire for 14 hours. The fix is to make cutover an operation you can undo in seconds, not a door that locks behind you.

The pattern

Run two identical production environments — blue and green. Blue serves all live traffic; green runs the new version, fully deployed and health-checked, receiving nothing. Cut over by switching traffic at the router (load-balancer listener, target-group swap, or weighted DNS) from blue to green in one atomic flip. Keep blue warm and untouched through a soak window: if green misbehaves, you roll back by flipping the router back to blue — no redeploy, no rebuild, no data archaeology. The deploy and the rollback are the same one-line operation in opposite directions.

How to apply it

  1. Stand up green at full size, beside blue. Same instance count, same config, same database. Both environments point at one shared database, so the schema must be readable and writable by both the old and new code — this is the hard prerequisite: pair blue-green with expand-contract (parallel change) and never ship a destructive migration (DROP, RENAME, type-narrow) in the same release as the cutover (Drill 57). The destructive step ships later, alone, after the old version is gone for good.
  2. Gate green behind health checks before it sees a user. Require 5 consecutive 200s on /healthz, 10s apart (ALB healthy-threshold 5, interval 10s) before green joins the pool. Green receiving traffic while unhealthy is just a faster outage.
  3. Flip the router — atomically, not gradually. Swap the load-balancer listener/target-group from blue to green (instant; no DNS propagation wait). If you must use DNS, set the record TTL to 60s ahead of time so the switch propagates in a minute, not a day. Set connection draining / deregistration delay to 300s so in-flight requests on blue finish cleanly instead of being cut mid-response.
  4. Bake, then reclaim — in that order. Hold traffic on green for a soak of 30 min (or a full business cycle for decision systems), watching error rate < 0.1% and p99 latency within 10% of blue's. Keep blue warm the whole time. Only after the soak passes do you scale blue down — decommission is the last step, never a milestone in the middle (Drill 54).
  5. Make rollback a rehearsed one-liner. If any soak signal breaks, flip the listener back to blue in < 60s. No rebuild. Rehearse it: staging must actually roll each release back after deploying it — a rollback that's only ever been written down is a rumor with a checkbox.
flowchart TD
    A["Green deployed at full size<br/>(shared DB, expand-contract schema)"] --> B["Health gate: 5x 200 on /healthz,<br/>10s apart, before joining pool"]
    B --> C["Flip router: listener blue to green<br/>(instant; drain 300s)"]
    C --> D["Bake 30 min: error rate < 0.1%,<br/>p99 within 10% of blue"]
    D -->|"soak clean"| E["Scale blue down last —<br/>decommission is the final step"]
    D -->|"any signal breaks"| F["Flip router back to blue<br/>in under 60s — no redeploy"]

When to use it — and when not

Reach for it on any stateless service where the cutover risk is worth doubling infrastructure for a soak window — payment APIs, decisioning systems, anything whose rollback is worth 14 hours. Skip or adapt it when: (a) the fleet is huge and 2x capacity is prohibitive — prefer canary / rolling (shift 1% → 10% → 50% → 100%) which trades instant rollback for cheaper overlap; (b) the change is destructive to shared state — blue-green rolls back code, not data, so a dropped column or a rewritten format still needs expand-contract first, and a data migration needs a parallel run (Drill 54), not a router flip; (c) long-lived stateful connections (WebSockets, in-flight sessions) that can't be drained in 300s. The cost is real: double the infrastructure for the overlap, and a backward-compatible schema discipline on every migration. Don't pay it for a static site or a change you could safely roll forward.

Signals it's working

Seen in the wild

See it

TilesScene shows the two environments and the health gate (5× 200, 10s, drain 300s); ChainScene carries the atomic router flip → bake → blue scales down last; CardsScene holds the load-bearing numbers (30-min soak, error < 0.1%, p99 within 10%, rollback < 60s); LayersScene names the tradeoff — code rolls back, data does not, so pair with expand-contract.

Named concepts: blue-green deploy, reversible cutover, instant rollback, traffic switch at the router.