When you run fly deploy, Fly performs a rolling deployment by default:
Old Machine v1 (running)
New Machine v2 (starting)
│
▼ health check passes
New Machine v2 (healthy)
│
▼ Fly proxy shifts traffic
Old Machine v1 (stopped / destroyed)
At no point is there a gap in service — the old Machine handles traffic until the new one is proven healthy.
Replaces Machines one at a time. Zero downtime.
fly deployCreates all new Machines before cutting over. More resource-intensive but instant cutover.
fly deploy --strategy bluegreenSends a small % of traffic to the new version before full rollout.
fly deploy --strategy canaryStops old, starts new without health check waiting (fastest but brief downtime).
fly deploy --strategy immediateFly won't mark a Machine as healthy (and won't cut over traffic) until health checks pass.
[[http_service.checks]]
grace_period = "5s" # Wait before checking after start
interval = "10s"
method = "GET"
path = "/health"
timeout = "2s"Your app must return HTTP 200 on /health before Fly considers the deploy successful.
Run a command before new Machines start (e.g., database migrations):
[deploy]
release_command = "python manage.py migrate"The release command runs in a temporary Machine using the new image. If it fails (non-zero exit), the deploy is aborted.
This is the correct pattern for database migrations — run migrations before routing traffic to new app code.
fly deploy --image registry.fly.io/my-app:<previous-deployment-tag>fly releasesOutput:
VERSION STABLE TYPE STATUS DESCRIPTION USER DATE
v10 true release complete deploy user@ex 1h ago
v9 true release complete deploy user@ex 3h ago
fly deploy --image registry.fly.io/my-app:deployment-01ABCDfly deploy --wait-timeout 120 # Wait up to 120s for deploy to completefly logs # Watch live logs during deploy
fly status # Check Machine statesfly deploy --image nginx:1.25
fly deploy --image ghcr.io/myorg/myapp:v1.2.3- Deploy your app.
- Modify the app (change a response message).
- Run
fly deployand in a parallel terminal runfly logs— observe the deploy process. - In a third terminal, curl your app repeatedly during the deploy:
watch -n 0.5 curl -s https://my-app.fly.dev— confirm no errors.
- Add a simple release command (e.g.,
echo "Migration complete") tofly.toml:[deploy] release_command = "echo 'Running migrations...'"
- Deploy and watch the logs — you should see the release command output.
- Make a breaking change to your app.
- Deploy it.
- Run
fly releasesto find the previous version. - Roll back with
fly deploy --image registry.fly.io/<app>:<old-tag>.
→ Continue to 1100 — Volumes & Persistent Storage