Zero-downtime deploys on a single Linux server with atomic releases
You do not need a container platform to deploy without downtime. How atomic release directories, symlink switching, health checks, rollbacks and least-privilege deploy users give a single Linux server safe, repeatable deployments.

An atomic deployment builds each release in its own directory and switches traffic to it in a single filesystem operation, so visitors never see a half-updated site. It is an old, dependable technique that gives a single Linux server — or a small fleet — safe deployments and instant rollbacks without a container orchestration platform. This site itself is deployed this way.
The directory layout
/var/www/example.com/
├── releases/
│ ├── 20261001T101500/
│ └── 20261001T143000/
├── shared/ # files that persist across releases
└── current -> releases/20261001T143000
The web server’s document root points at current. Releases are immutable once built.
The deployment sequence
- Fetch the code at a specific commit into a new release directory.
- Build — install dependencies and compile assets inside that directory.
- Link shared resources — uploads, environment files, caches — from
shared/. - Verify — run a smoke test against the built output.
- Switch — create a temporary symlink and rename it over
current. - Reload services that need it, such as PHP-FPM or an application server.
- Clean up — keep the last few releases, delete older ones.
If any step before the switch fails, the live site is untouched.
Making the switch truly atomic
ln -sfn removes and recreates the link, leaving a tiny window. Renaming is atomic on the same filesystem:
ln -s "releases/$RELEASE" current.tmp
mv -Tf current.tmp current
mv -T treats the target as a file, replacing the link in one rename system call.
Static sites and dynamic applications
For a static site, the switch is the whole deployment: Nginx serves the new files on the next request. For PHP applications, reload PHP-FPM after the switch, because OPcache and the realpath cache can keep serving old paths; or configure the server to resolve the real path of the release. Long-running application servers need a graceful restart that lets in-flight requests finish.
Database migrations
Atomic file switching does not make schema changes atomic. Use backward-compatible migrations: the old release must keep working against the new schema during the switch. Add columns before code uses them, and remove them only after code stops using them. This expand-and-contract method is covered in scaling MySQL for transactional platforms.
Least-privilege deployment
Security improves noticeably when deployment does not run as root:
- a dedicated deploy user with no login shell,
- a read-only deploy key for the repository,
- write access only to the release directories,
- a narrowly scoped rule for the one service reload it needs, if any.
If the pipeline or a dependency is compromised, the blast radius stays small.
Triggering deployments
Options range from a manual command to automated pulls:
- a systemd timer that checks for new commits and deploys when the branch changes,
- a webhook from the Git host that triggers the deploy script,
- a CI pipeline that builds artefacts and ships them to the server.
A timer is the simplest and needs no inbound access; webhooks deploy faster; CI moves build work off the server.
Rollback in seconds
Because earlier releases remain on disk, rollback is the same switch in reverse: point current at the previous release and reload. Make it a single command, and practise it before you need it.
Observability for deploys
Log every deployment with commit, time and result. Watch error rates and latency for a few minutes after each switch, and roll back automatically if health checks fail.
The takeaway
Atomic releases, a symlink switch, backward-compatible migrations and a least-privilege deploy user give small infrastructure the deployment safety usually associated with large platforms. The technique is simple, transparent and easy to reason about at three in the morning — which is exactly what deployment tooling should be. Related infrastructure patterns are in Redis beyond caching.
Frequently asked questions
How do atomic deployments work?
Each deployment is built into a new timestamped release directory. When the build succeeds, a symbolic link such as current is switched to the new directory in a single atomic rename, so the web server always serves either the complete old release or the complete new one.
How do you roll back an atomic deployment?
Point the current symlink back to the previous release directory and reload any services that cache file paths. Because previous releases are kept on disk, rollback takes seconds and needs no rebuild.
Should deployments run as root?
No. A dedicated, non-login deploy user with read-only access to the repository and write access only to the release directories limits the damage if the deployment pipeline or a dependency is compromised.