02 Oct 2026 · 6 min read
Deploy and rollback with Govard
Rehearse every Govard deploy in a sandbox with plan, check, deploy, and rollback steps before production traffic sees it
Part 6 of the Govard in Depth series — the deploy loop that makes releases boring on purpose.
Why deploys go wrong
Most failed deploys are not mysterious. The code was fine on a branch, the database migration was fine on staging, and the combination failed in production at the worst possible hour. The usual causes form a short list: an untested migration order, a config value that exists locally but not on the target, static content built against the wrong mode, or a deploy step that nobody rehearsed because rehearsing felt slower than shipping.
Govard answers this with a loop rather than a single command: plan, check, rehearse, deploy, and rollback as a first-class step rather than a panic procedure. Each stage catches a different class of mistake, and each one is cheaper than the one after it. A plan you can read is cheaper than a check that fails; a check that fails is cheaper than a rehearsal that breaks; a rehearsal that breaks is dramatically cheaper than a production rollback at midnight.
The goal is not to make deploys exciting. It is to make them boring: the same sequence every time, with the same gates, producing the same artifact, against an environment you have already proven the artifact works in.
The deploy loop: plan, check, rehearse, deploy
Start with the plan. Before anything runs, Govard shows what it intends to do: which target, which release artifact, which migrations, which config changes, and in what order.
# See the full deploy plan without executing anything
govard deploy plan --target staging
# Run pre-flight checks: versions, connectivity, disk, config drift
govard deploy check --target staging
The plan output deserves a slow read. Check the migration list against what you merged: are there migrations from two branches interleaved in an order nobody tested? Check the config diff: does the target carry every key the release reads, or did someone add a feature flag locally and forget to set it on the server? The check command automates the mechanical half of this review. It verifies target reachability, compares PHP and service versions between the artifact and the target, flags configuration drift, and confirms disk headroom for a release plus a retained previous release for rollback.
Then rehearse. Govard can run the full deploy against a disposable sandbox that mirrors the target, including the database migration path, before production ever sees the artifact:
# Full rehearsal against an isolated sandbox copy of the target
govard deploy rehearse --target staging --from prod-snapshot
# When the rehearsal is green, run the real deploy
govard deploy --target staging
govard deploy --target production
The rehearsal is where migration-order bugs surface. It runs the real migrations against a recent snapshot, builds static content in production mode, warms the caches the release needs, and exercises the smoke checks: homepage, a category page, add-to-cart, checkout entry. If static content fails because a LESS file references a missing variable, you learn it in the sandbox in minutes rather than in production with traffic waiting. Promote the identical artifact through staging to production rather than rebuilding per target; a rebuild is a new artifact with new ways to differ.
Between rehearsal and production, freeze the inputs. No new commits into the release branch, no manual config edits on the target, no "quick fix" applied by hand on the server. Every out-of-band change invalidates the rehearsal you just paid for. If something must change, re-run plan and check at minimum, and re-run the rehearsal if the change touches migrations, configuration, or build inputs.
Rollback is a step, not a panic
Every Govard deploy keeps the previous release on the target until the new one is verified. Rollback is therefore a single, rehearsed action: point traffic back, restore the pre-deploy database checkpoint where the strategy requires it, and confirm.
# Inspect release history on the target
govard deploy history --target production
# Roll back to the previous known-good release
govard deploy rollback --target production --to previous
# Verify after rollback: health, version marker, smoke paths
govard deploy status --target production
govard tool magento cache:flush
Two decisions need to be made before the deploy, not during the incident. First, the database strategy: code rollback is instant, but migrations that already ran do not un-run themselves. Know for each release whether rollback means code-only revert (migrations were additive and backward compatible) or code plus database restore from the pre-deploy checkpoint, and write that down in the release notes. Backward-compatible migrations, expand then contract, are what make code-only rollback possible; a migration that drops a column the old code still reads makes code-only rollback a second outage.
Second, the verification gate: decide in advance what "good" looks like after both deploy and rollback. A short list suffices: HTTP 200 on the homepage and one category page, add-to-cart succeeds, checkout page renders, error rate within baseline, and the version marker matches the intended release. Run the same gate both directions. A rollback nobody verified is just a second unreviewed deploy.
Practice the rollback path in staging at least once per quarter. Teams that have only ever read the rollback docs discover, under pressure, that they lack credentials on the target, that the retained previous release aged out, or that the database checkpoint flag was never enabled. A fifteen-minute drill in staging answers all three questions for free.
Pitfalls
- Rebuilding the artifact per target. Building once and promoting the same artifact through staging to production eliminates an entire class of "works on staging" divergence. Rebuilds are for new releases, not new targets.
- Skipping the rehearsal under time pressure. The release that "cannot wait for a rehearsal" is exactly the release most likely to need a rollback. The rehearsal is the cheapest stage that runs real migrations.
- Manual server edits during a release freeze. A hand-applied config fix on production invalidates the rehearsal and guarantees the next deploy reverts it. Put the fix in the branch and re-run the loop.
- Irreversible migrations without a database plan. Dropping columns, renaming tables, or backfilling destructively in one step removes the code-only rollback option. Split into expand and contract phases across releases.
- No retained previous release. If retention is misconfigured and the old release is already garbage-collected, rollback becomes redeploy-from-scratch at the worst moment. Verify retention as part of the check stage.
- Verifying deploys but not rollbacks. The smoke gate must run identically after a rollback. An unverified rollback that serves stale static content or a half-flushed cache reads as a second incident to customers.
Next in this series: Day one on a new project with Govard — /blog/govard-onboarding-day-one