A deploy on most simple hosts means "stop the old container, start the new one" — which drops requests during the gap and strands you if the new image is broken. App VMs avoid both failure modes with a run-new-then-swap model.
The deploy model
When you deploy, the App does not touch the running container first. Instead it:
- Pulls the new image.
- Starts the new container alongside the old one, on a separate internal port.
- Health-checks the new container.
- Only once the new container is healthy, swaps inbound traffic to it and removes the old one.
Until step 4 succeeds, every request is served by the old container. There is no window where nothing is listening, so the swap is invisible to your users.
The health check is the gate
The health check is what decides whether the swap happens. If you set a health path, the new container must return an HTTP 2xx on it; if you did not, a plain TCP connection to your container port must succeed. The check retries until a timeout.
This means a broken image cannot take your App down. If the new container never becomes healthy, the swap is skipped, the old container keeps serving, and the deploy is recorded as failed with an error you can read.
Rollback is a deploy in reverse
A rollback reuses the same machinery, targeting a previous successful deploy. Because each succeeded deploy records the image's content digest, a rollback redeploys the exact bytes that ran before — not whatever the tag points at now. That makes rollbacks deterministic even if you have since overwritten the tag.
A rollback restores the image only. Environment variables and persistent-volume contents are not versioned, so they are whatever they currently are.
What survives a deploy
The optional persistent volume is a property of the VM, not the container. It is bind-mounted into whichever container is live, so it survives deploys, restarts, and stop/start. It is deleted only when you destroy the App. Anything your container writes outside the volume path lives only as long as that container and is gone after the next deploy.
Volume-backed Apps and the brief pause
Apps with a persistent volume cannot use the run-new-then-swap model described above. The reason is data integrity: two versions of a stateful application must never write to the same data directory simultaneously. A database, a queue, or any application that holds an exclusive lock on its data directory would corrupt its state if two containers ran concurrently.
For volume-backed Apps, the deploy sequence is:
- Pull the new image.
- Stop the current container (graceful shutdown, up to 30 seconds).
- Start the new container — it mounts the volume at the point the previous container released it.
- Health-check the new container.
If the new container fails its health check, the previous container is restarted and the deploy is recorded as failed. Your data directory is intact. The trade-off is that there is a brief window between step 2 and the new container serving — users may see connection errors during this window. If your application does not need a persistent volume, removing it restores the zero-downtime guarantee.