A zero-downtime Laravel deployment is not a shell command that swaps a symlink. It is a compatibility discipline: old and new application processes may run at the same time, workers may still hold old code, and the database must serve both versions during the rollout.

Build one immutable release

CI should produce a known artifact or image with locked Composer and frontend dependencies. The same artifact moves through staging and production. Installing changing dependencies on the server makes rollback and investigation less reliable.

Record the commit and release ID in logs and a health endpoint so an incident responder can see exactly what each instance runs.

Make database changes backward compatible

Destructive migrations are the most common barrier to safe rollout. Use an expand-migrate-contract sequence:

  1. Add a nullable column or new table without removing the old shape.
  2. Deploy code that can work with the transition and write the new data.
  3. Backfill existing rows in controlled batches.
  4. Switch reads after verification.
  5. Remove the old structure in a later release.

Large indexes and table alterations need an online migration plan. A logically correct migration can still lock a busy table.

Warm the release before receiving traffic

Install dependencies and build configuration, route, and view caches before the release becomes active. Run a readiness check that boots Laravel and verifies essential configuration. The load balancer should only send requests after readiness succeeds.

Switch traffic atomically

Symlink-based releases, containers, blue-green environments, and rolling instances can all work. The key is that users never see a half-copied directory. Keep enough previous releases for a fast code rollback and clean old artifacts later.

Restart long-running workers gracefully

Queue workers keep application code in memory. Signal a graceful restart after the new release is available; current jobs finish and replacement workers load new code. Job payloads must remain compatible if old queued data is consumed by the new release.

Scheduler overlap and duplicate execution should be controlled with locks where the task cannot safely run twice.

Treat health checks as product checks

Liveness asks whether a process should be restarted. Readiness asks whether it can handle traffic. A post-deployment smoke test should exercise a safe critical path, not only request a static page. Watch error rate, latency, queue failures, and business events during a defined observation window.

Rollback needs a database story

Rolling back code is easy when the new release only added compatible schema. It is dangerous when it changed data meaning or performed irreversible work. For those releases, prepare a forward fix, reconciliation script, or restore decision in advance.

Keep deployment boring through rehearsal

Use the same pipeline regularly, document manual approvals, and practice rollback before an emergency. Reduce one-off SSH commands. A release checklist should identify migration risk, worker impact, cache changes, and the person watching production.

Deployment reliability depends on application design as much as infrastructure. For help reviewing that boundary, see Laravel development and deployment or the technical audit service.

Frequently asked questions

Can every database migration be zero-downtime?

Not as a single step. Destructive changes usually need expand-migrate-contract phases so old and new code remain compatible during rollout.

Why restart queue workers after deployment?

Long-running workers keep old application code in memory. A graceful restart lets current jobs finish and new processes load the release.