What Happens When You Redeploy — and Why You Get One Second to Shut Down
When you redeploy, your container is stopped, removed, and recreated — nothing runs in parallel, so there is a real gap where your app is down. The sequence is: send the stop signal, wait about a second, kill whatever is left, remove the container, pull or build the new image, create a fresh container with your volumes and environment reattached, start it. Knowing the order matters because two things surprise people: the graceful-shutdown window is roughly one second, and changes you wouldn't think of as deploys — adjusting a CPU quota, editing an environment variable — go through exactly the same path.
The sequence
- Stop. The running container gets a termination signal and a very short grace period.
- Kill. Anything still alive after that is killed outright.
- Remove. The container is deleted, and its writable layer goes with it.
- Pull or build. A registry image is pulled; a git or zip deploy has already built one.
- Create. A new container is assembled — your volumes remounted, environment variables and ports reapplied, labels rebuilt.
- Start. The entrypoint runs and your process begins.
Your downtime is all six steps plus however long your app takes to become useful — which, for anything that connects to a gateway or warms a cache, is usually the longest part.
There's no blue/green here and no request draining. If you need genuine zero-downtime, that's a property this platform doesn't offer; what it offers instead is that the gap is short and the restart is automatic.
You get about one second to shut down
This is the part worth internalising. The stop is issued with a kill timeout of roughly one second — your process gets a termination signal, and a moment later it's killed whether or not it finished.
That's enough time for almost nothing. In practice:
- A long graceful-shutdown handler will not complete. A bot that closes its gateway connection politely over five seconds gets cut off after one.
- Buffered writes can be lost. If your app batches database writes or holds an open transaction, assume it dies mid-flight.
finallyblocks and atexit hooks are not guarantees. They run only if the process is still alive to run them.
So design for being killed, not for being asked nicely:
- Commit as you go. Write state when it changes rather than on shutdown.
- Make startup idempotent. Assume the previous run stopped at the worst possible moment — a half-finished job should be safe to redo.
- Don't keep anything important only in memory. If it matters after a restart, it belongs on a volume or in a database.
None of this is unusual advice for containers. It just matters more when the window is this narrow.
What survives and what doesn't
Survives: volumes and everything in them, environment variables, config files, port bindings, quotas. All of it is stored against the app, not the container, and gets reapplied to the new one.
Doesn't survive: anything written outside a volume. The writable layer is discarded with the old container, which is why a database next to your code resets on redeploy — and why a crash-restart, which reuses the same container, doesn't have that effect. Same word, different event.
Also doesn't survive: in-memory state. Caches, counters, scheduler state, the position of anything you were part-way through. In-process schedules reset — a job due during the gap doesn't fire.
What counts as a redeploy
More than pushing new code. The full recreate path is triggered by:
- Deploying a new image (git push, docker push, zip build)
- Changing registry URL or credentials
- Changing the CPU or RAM quota
- Changing the run command
- Adding or editing environment variables
- Adding or editing config files
- Adding or removing ports
- Adding or removing volumes
The quota one catches people out — nudging memory up feels like a settings tweak, not a deploy, but the container has to be recreated to take the new limit. Batch your configuration changes into one edit rather than saving six times.
Making deploys less disruptive
You can't overlap the old and new containers, but you can shorten and schedule the gap:
- Build without deploying. If you deploy by git, pushing to the
buildbranch builds the image and attaches it without restarting — so you can bake the image whenever CI finishes and roll it out when you choose. More on the branch split. - Make startup fast. Lazy-load anything you don't need in the first second. Time spent loading a dataset at import is time your app is down.
- Batch config changes. One edit, one restart.
- Deploy when it's quiet. For a community bot, that's not during your busiest hours.
- Test on a staging app first, so the production gap happens once and for a change you already know works — a second app costs only what it uses.
After it starts
Two things about the new container that are easy to misread:
- A supervised restart loop means "running" isn't "working." If your process exits immediately, the entrypoint restarts it every five seconds and the status stays green. Read the logs for the exit-code line.
- The first start is the slowest. A registry image has to be pulled before the container can be created; subsequent deploys of the same image skip that.
FAQ
Does redeploying cause downtime?
Yes. The old container is stopped and removed before the new one is created — nothing overlaps. The gap is short but real.
How long does my app have to shut down cleanly?
About a second. The process gets a termination signal and is killed shortly after, so long graceful-shutdown routines won't finish.
Does changing an environment variable restart my app?
Yes. Env vars, config files, ports, volumes, quotas, and the run command all require the container to be recreated.
Will I lose data when I redeploy?
Anything in a volume survives. Anything written elsewhere in the container is discarded along with the old container, as is all in-memory state.
Can I do a zero-downtime deploy?
No. There's no blue/green or request draining. You can shorten the gap with fast startup, and separate building from deploying by pushing to the build branch.
Why did my scheduled job not run?
If it was due during the redeploy gap, nothing queued it — in-process schedulers reset when the container is recreated.
Wrapping up
The mental model that avoids most surprises: a redeploy isn't a restart, it's a replacement. A new container, a fresh filesystem, your volumes and settings reattached — and about a second between the old process being asked to stop and being made to. Write state as it changes, make startup idempotent, and batch your config edits, and the gap becomes a few seconds of downtime rather than a source of corrupted data.