Kingsfordweg 151, 1043GR Amsterdam, The Netherlands ● 24/7 support — support@novogara.com
Knowledge base

Deploying without downtime

Most outages are deployments. The good news is that this is the failure you have the most control over.

Atomic releases

Never edit files in place in a live directory. Build the new version beside the old one and switch with a symlink:

/srv/app/releases/2026-10-14-1530/
/srv/app/current -> releases/2026-10-14-1530

ln -sfn onto a temporary name and mv -T it into place, so the switch is a single atomic operation. No request ever sees a half-copied tree.

Keep the last five releases. Rollback then becomes moving the symlink back and reloading — seconds, not a rebuild.

Reload, do not restart

gunicorn reloads on HUP, PHP-FPM on USR2, nginx on reload. Old workers finish what they are doing and new ones pick up the new code. Your own application should handle SIGTERM the same way — see running your application as a service.

If you set opcache.validate_timestamps=0 as PHP-FPM tuning recommends, the reload is not optional: your new code is not used until it happens.

Migrations are the dangerous part

A rollback cannot undo a dropped column. Make migrations additive and split them across deploys:

  1. Deploy 1 — add the new column, write to both, read from the old
  2. Deploy 2 — read from the new
  3. Deploy 3, days later — stop writing the old, then drop it

Tedious, and it means any single deploy is reversible. Watch for migrations that lock a large table: adding an index on a busy table can stall writes for minutes. Use the concurrent or online variants, and rehearse against a copy of production data.

Run migrations as their own step

Not at application start-up, or every worker races through them at once. One command, before the symlink switch, with its own exit code that aborts the deploy if it fails.

A pipeline worth having

  1. Tests run on every push
  2. The artefact is built once and the same one goes to staging and production
  3. Deploy to staging automatically
  4. Production needs a human to approve
  5. Health check afterwards, automatically, with an automatic rollback if it fails

The deploy user on the server gets exactly the sudo rights it needs and no more — one line in sudoers for the reload, as users and sudo describes.

Two rules

Do not deploy on Friday afternoon. Not superstition: if something surfaces two hours later, you want people awake and available.

Practise the rollback. A rollback that has never been executed is a theory, in exactly the way an untested restore is. Do it once on purpose, on staging, and time it.


Still stuck? Mail support@novogara.com — an engineer answers, at any hour. Back to the knowledge base