Zero-downtime deploys
A release starts the new code next to the old code and then moves traffic over. You are not sent through a restart: a reply that is already streaming, or a file upload that is already under way, finishes on the old copy.
Diagram as text
- Visitors, the tunnel and worker machines connect to port 8080. An nftables table named zl_zdt redirects that port to the active proxy.
- The front-door proxy runs as two instances, zerolog-proxy@a on port 8084 and zerolog-proxy@b on port 8085. Only one receives traffic at a time.
- The proxy forwards HTTP, server-sent events, WebSocket upgrades and CONNECT requests to the active app slot: zerolog@blue on port 8082 or zerolog@green on port 8083.
- deploy.sh tests the new code, takes a backup, then starts the idle slot, health-checks it and activates it. It reloads the proxy so the new slot takes traffic. If the proxy code itself changed, it starts the other proxy instance, health-checks it, moves the nftables redirect over and stops the old instance.
- The old slot gets SIGTERM and drains. The proxy keeps follow-up requests of chats and uploads that began on it on that slot until they finish.
- deploy.sh restarts zerolog-worker, which drains its running jobs first.
How a release goes
- Test in isolation. The new code is tested in an isolated copy first: lint and the test suite. Only green code moves on.
- Back up. A backup is taken before anything on the live system changes.
- Check the database changes. Old and new copy share one database for a few moments, so a release that drops or renames a table or column, or adds a required column without a default, is refused.
- Start the idle slot. It starts with the new code. If it does not pass its health check, the active slot keeps serving and the release stops there.
- Move traffic. The new slot is activated and the front-door proxy is told to send traffic to it. If the proxy's own code changed, a second proxy instance starts, is health-checked, and the port redirect is moved to it before the old instance stops.
- Drain the old slot. Follow-up requests of chats and uploads that began on it are kept on it until they finish; it is stopped after at most ten minutes.
- Restart the worker. The background worker restarts and finishes its running jobs first, for at most five minutes.
- Smoke test. A smoke test runs against the slot that is now active.
What it does not do
A reply that is still running when the old copy's ten minutes are up is cut off. A release that removes or renames database columns is refused in the normal path and needs a planned two-step release instead. None of this is something you configure.
Going back
The operator can return to the single-process setup. The old process starts and is health-checked while the proxy keeps serving; only then does traffic move to it, and the proxies and slots are removed last.
Related: Isolation, Trust and security, Status.