Skip to main content
Percher is still being built and account creation is paused — get notified when it opens.

Zero-downtime deploys

Drain + canary + auto-rollback

Ask your agent
Make sure my app stays up while I publish updates.Read the guide at percher.app/docs/graceful-deploys
How it works, with exact details

Every live deploy goes through a drain-and-swap sequence: the new container starts, passes its health check, takes over traffic via an atomic Caddy route swap — and the old container is stopped only once the post-deploy canary settles, so a failed canary still has the previous version to restore.

A 60-second canary monitor probes the new version after the swap. If two probes return 5xx in a row, Percher rolls back: restores the previous version’s upstream and the access settings it was serving under — password protection, visibility, redirects, response headers and rate limit all go back with it — stops the failed container, and marks the deploy failed. A rollback never leaves a protected app public because the deploy that failed asked for public.

When the previous containers are already gone — they crashed on their own, or an operator removed them — there is nothing to restore, so Percher leaves the new container running instead of taking the app down. It does the same on the rarer occasions when it can restore the route but cannot safely finish the bookkeeping: nothing that might still be serving is destroyed on the strength of a rollback Percher could not complete. The deploy is marked failed either way. You see this live in the dashboard as a stepper — Build → Start → Health check → Swap → Canary → Live — with a rollback row if the canary fired; read the message on that row rather than its heading, which only has two words to work with.

The canary window and automatic rollback are settings of the Percher instance, not of your app: on percher.app the window is 60 seconds and auto-rollback is on for every app. Setting PERCHER_CANARY_AUTO_ROLLBACK, PERCHER_CANARY_WINDOW_MS or PERCHER_DRAIN_GRACE_MS as an app environment variable has no effect; they apply only to a self-hosted Percher API.

Post-deploy screenshots (preview). Once a deploy is live, Percher can capture a screenshot of your app and attach it to that deploy (surfaced as screenshotUrl on the deploy result). It's a preview feature, off by default, and strictly best-effort — a screenshot never delays or fails a deploy. Only public apps are captured; a password-protected or private app is skipped (Percher never logs in to take the shot). The capture hits your app's public URL through a locked-down headless browser that can only reach your own app's hosts — it can't be pointed at anything internal.