June 6, 2026 · 6 min read

The deploy I never think about: zero-downtime releases that roll themselves back

Two outages taught me to stop hoping. Build-stamped smoke gates, run-from-package, and atomic slot swaps mean you can never silently ship the wrong build.

The deploy that taught me the most went out green and took production down hours later. The pipeline had pruned dev dependencies before packaging, the prune went too far, and an effectively empty dependency tree shipped inside the artifact. Tests had passed. The build was clean. Then a worker restarted later in the day, failed to import a core dependency at startup, and the portal went dark for a contractor in the middle of their workday.

That outage, and a second one where the platform's startup optimizer got stuck in a tarball-extraction crash loop on cold start, are the reason the deploy pipeline looks the way it does now. Every piece of it is a scar.

Start with the prune. Immediately after dev dependencies come out, the pipeline now checks that a handful of named production dependencies still physically exist on disk. If they do not, the build dies right there, before anything leaves CI. A green test run proves the code works. It does not prove the thing you are about to ship can boot, and those are different claims, which I learned the expensive way.

Then the artifact itself. App Service Run-From-Package takes a ZIP and nothing else. An early attempt to slim the artifact produced a tar file wearing a .zip extension, and the platform rejected the mount with an error that ate an afternoon. So the pipeline will not upload until it has checked three things about the blob: the file-type magic actually says ZIP, the archive passes an integrity test, and the runtime paths sit at the archive root instead of nested under a folder. A bad artifact dies in CI, not on the slot.

Run-From-Package is the change that ended the crash loops. The uploaded ZIP gets mounted read-only as the web root. Nothing extracts, the startup optimizer never runs, and the whole tarball-extraction failure class becomes structurally impossible, because there is no writable web root left for it to fail inside. The pipeline does not set the flag that enables this on every deploy, because a per-deploy settings write forces an extra restart and invites a race. It asserts the flag is already present and stops if it ever drifted, since a silent fallback to the old extract-into-place behavior would quietly invite the crashes back.

The subtlest scar is the smoke gate. Asynchronous deploys have a trap: the new code is uploaded but the running container is still serving the old code, and a lazy health check gets a cheerful 200 off the stale build and calls it a win. I hit exactly that. So every build now stamps a version.json with its build number, and a /api/smoke endpoint serves it. The gate does not wait for any 200. It waits for the build number in the response to match the build it just produced. Until those match, a 200 means the old code is still up, and the gate keeps waiting. The right build cannot be faked by accident.

Promotion to production is an atomic slot swap, a hostname flip with no extraction and no restart of the live container, which is what makes the cutover invisible. The previous production code lands in the staging slot and becomes the rollback target. After the swap, a production smoke check runs the same build-stamped gate and also demands a healthy database connection. If it fails, an auto-rollback step re-swaps to the previous code on its own and marks the run failed so the failure is loud. And because Run-From-Package keeps the five most recent packages, a manual rollback is a sub-minute repoint to a prior one, not a fresh upload under pressure.

I do not watch deploys anymore. I merge and move on. The last time a swap went bad the pipeline re-swapped before I had read the alert, and the contractor's project managers never knew anything happened. A deploy that used to be a knot in my stomach is now the most boring part of my week, and that boredom is the deliverable. It is what lets one engineer run production for a real company without living on call.

This is the kind of operational floor I build under the AI systems I ship for clients, embedded on their team, in their cloud. If your deploys still need a human babysitting them, that is fixable, and it is a good first conversation at /contact.

Want this kind of work in your business?

See the service that fits, or book a 30-minute call and tell me what you're working on.