Back to Explore
NewsVibeFix 编辑部Updated Oct 31, 2026

Deploys No Longer Interrupt In-Flight Work: Cloudflare Durable Objects Defer Code Updates by Default

On 30 October 2026 Cloudflare made Durable Objects defer code updates by default: an active object can keep running old code for up to 5 minutes until it hibernates, and Hibernation API WebSockets stay connected. But 5 minutes is a grace period, not a guarantee — idempotency and resumable steps still matter.

A data center corridor lined on both sides with rows of server racks with blinking indicator lights

A data center corridor lined on both sides with rows of server racks with blinking indicator lights

When you deploy new code, the scariest part is often not that the new code is broken, but that the old code gets cut off halfway through something it was doing. On 30 October 2026, Cloudflare changed the default behaviour of Durable Objects: from now on, a deploy no longer replaces running code immediately. Instead, code updates are deferred by default. An active object can keep running its current code for up to 5 minutes while it waits to hibernate. It is a small change, but a genuinely useful one: it turns deploying from an operation that interrupts users into one that can quietly happen in the background.

To understand the change, you first need to understand what Durable Objects actually are. They are not ordinary stateless functions. An ordinary function finishes one request and is done; the next request may run on a different machine, on a different version. A Durable Object is different: each object is globally unique, and it can run only one version of your code at a time. That combination of uniqueness and single-version execution is what lets it do jobs other services cannot easily do: hold a long-lived chat room where dozens of people exchange messages in the same room; keep the live state of a game so every player sees the same match; run a long-running agent task that advances step by step and remembers how far it has got.

But that strength used to come with a cost. Since only one version can run at a time, deploying new code meant the running old version had to give way. The old behaviour was to apply the change immediately: in-flight work could be interrupted and open connections could be terminated. For users, that showed up as a chat suddenly disconnecting, game state being lost, or an agent task stopping halfway with no follow-up. For developers, it showed up as a habit of choosing deploy times carefully — late-night releases, weekend releases, or even waiting until users were asleep. That is a reluctant habit, not a good workflow.

The new default: let the old code finish first

Under the new default, updates are deferred. After you deploy, an active object does not switch code straight away. It keeps running the old code while it waits for a suitable moment to switch. That moment is hibernation. In plain language, hibernation means the object has nothing to do for the moment, so it goes to sleep; the next time a request comes in, it wakes up, and when it wakes up it can start directly on the new code. For users, the switch is almost invisible, because it happens between two requests rather than in the middle of one.

The flow works like this: you deploy new code; the active object keeps running the old code; if it hibernates before the delay ends, the next request starts on the new code; if the delay ends first and it has not hibernated, it resets and adopts the new code. There is also a manual path: if you explicitly choose immediate mode for a particular deploy, the object resets and adopts the new code right away. Drawn as a flowchart it looks simple, but it fixes exactly the most painful part of the old behaviour: deploying no longer means interrupting by default.

One detail deserves to be called out separately: WebSocket connections that use the Hibernation API stay connected when an object adopts new code after hibernating. In other words, users in a chat room do not get dropped just because a deploy happened. Their connection is still there; only the code version behind it has quietly changed. That matters a great deal for real-time applications. In the past, many teams had to build reconnection, resume-on-disconnect, and state recovery in their own application layer just to survive deploys; now the platform takes over the hardest part of that job. That does not mean every WebSocket connection survives automatically — the precondition is that you use the Hibernation API. If you do not use that API, you still need to judge deploy behaviour by your own connection management, not assume it.

Why this matters most for vibe projects

Many vibe projects are exactly the kind most hurt by the old behaviour. A small product built by one person with AI often has no dedicated operations team and no elaborate release process; deploying is a button click or a code push. But the work it runs is not small at all: a chat assistant helping a user revise a resume step by step, an agent checking sources, calling tools, and writing a report, or a small game room where several people are mid-match. These jobs share one trait: they are not finished in an instant. They take time and continuity, and once interrupted they are hard to resume seamlessly.

Under the old behaviour, these projects often hit an awkward situation: the author fixed a small bug and happily shipped a new version, only for the users who were already using the product to suffer first — the conversation broke, the task stopped, the room scattered. Users do not know a deploy caused it; they simply conclude the product is unstable. And the author struggles to explain it: the code was getting better, so why did the experience get worse? Deferred updates ease that contradiction. New code can still ship, and in-flight work gets a chance to finish first. Deploy frequency can therefore go up, and authors no longer need to bundle ten small fixes into one big release just to avoid interrupting people.

More importantly, the change lowers the psychological cost of deploying. For solo developers and small teams, release cadence is part of iteration speed. If every deploy requires picking a quiet time, watching traffic, and hoping nobody is mid-task, iteration gets slower and more conservative over time. Deferred updates do not solve every problem, but they at least downgrade deploying from a high-risk operation to a routine one. For vibe projects that are still finding their direction and need to test quickly, that is real help.

Honestly: five minutes is a grace period, not a guarantee

This change is worth welcoming, but it should not be read as “deploys will never interrupt anything again.” Cloudflare states it plainly in the original post: a deferred code update is best effort and does not guarantee that every operation finishes. An object can still reset before max_delay is reached, and one explicit example is a Cloudflare runtime update. In other words, five minutes is a grace period, not an insurance policy. An object that has not hibernated after five minutes gets reset; an object hit by a platform-side reset before five minutes gets reset too.

That distinction matters because it decides how you should design your own program. If you treat deferred updates as a guarantee, you will write code that assumes “deploys will not interrupt me, so a task can run as long as it likes,” and then it will still break during some late-night runtime update. The right mindset is the reverse: deferred updates make most deploys gentler, but your program should still be built to survive being reset at any time. That is not a Cloudflare-specific problem; it is the general homework for all long-running tasks.

In practice, two things remain non-negotiable. The first is idempotent handlers: running the same operation twice should produce the same result as running it once. Charging a payment, sending a message, or writing a record must not cause a double charge, a duplicate send, or a duplicate entry just because a reset caused the step to run again. The second is resumable agent steps: after each step finishes, progress must be saved to durable storage, not kept only in memory. That way, even if the object resets, it can pick up from the last completed step when it wakes again, instead of starting over — or worse, repeating steps it already did. With those two in place, the benefit of deferred updates actually lands; without them, a five-minute grace period merely postpones the moment something breaks by five minutes.

There is another easily missed point: deferral does not mean old code can run forever. The default maximum delay is 300 seconds, five minutes. If you have a task that is destined to run for half an hour, it will still be interrupted by a deploy — just five minutes later instead of immediately. For such extra-long tasks, the right answer is not simply to crank the delay to its maximum, but to split the task into small steps, persist progress, and make it resumable by design. The delay setting is a buffer, not a solution.

Configuration: three lines to change, but think about how long the delay should be

The change is on by default, which means you do not need to do anything to get the default five-minute deferral. But if you want a longer or shorter delay, you can set it with code_update_strategy in your Wrangler configuration. The JSON form looks like this:

{
	"durable_objects": {
		"bindings": [
			{
				"name": "CHAT_ROOM",
				"class_name": "ChatRoom"
			}
		],
		"code_update_strategy": {
			"mode": "deferred",
			"max_delay": 60
		}
	}
}

If you use TOML configuration, the equivalent form is:

[[durable_objects.bindings]]
name = "CHAT_ROOM"
class_name = "ChatRoom"

[durable_objects.code_update_strategy]
mode = "deferred"
max_delay = 60

Here max_delay is in seconds, from 0 to 86400 — up to 24 hours — with millisecond precision. Omit it and you get the default of 300 seconds. There is no universal right answer for the length; it depends on your workload. For chat rooms and game rooms, where a single session usually lasts a few minutes, the default five minutes is often enough. For agent tasks with longer individual steps, a wider delay may make sense, but do not jump straight to 24 hours: the longer the delay, the longer old code stays live, and the later an urgent fix takes effect. That trade-off comes up again with immediate mode below.

Beyond the configuration file, you can also set the strategy for a single deployment. That is especially useful for teams that normally defer but occasionally need to go immediate, and the command looks like this:

npx wrangler versions deploy <VERSION_ID>@100% --durable-objects-code-update-mode immediate

Swap immediate for deferred plus a duration and you can use deferred mode for one deploy only. Note that the version id and percentage above are placeholders — replace them with your real values rather than copying the command verbatim. This per-deployment override is a good design: the default stays gentle, while special cases still get a fast lane, without editing the configuration file for one urgent fix and then editing it back.

When to deliberately use immediate mode

The gentle default is good, but it is not right for every moment. There are three situations where choosing immediate mode is the more responsible call. The first is a security incident: if old code contains a vulnerability that is being exploited, or it leaks data it should not, letting that code run for another five minutes means five more minutes of exposure. Do not hesitate — update immediately, even if it interrupts a few in-flight operations, because the cost of the security risk far outweighs a few interruptions.

The second is a broken deploy: if the version you just shipped is itself wrong, or you discover the previous version has a serious problem that only the new version fixes, deferral only prolongs the life of the bad code. Switch immediately so the correct code takes over as soon as possible. The third is post-deploy tooling that must hit new code. Cloudflare gives an example: your deployment tooling calls a Durable Object right after deploying and needs the new code. With the default deferral, that call might still land on old code, and the tooling would draw the wrong conclusion. For a flow of “deploy, then immediately verify, and the verification must see new behaviour,” a one-off immediate deploy is the cleanest approach.

The decision rule can be summed up in one sentence: deferral protects work that is already in progress, while immediate mode protects getting new code live as soon as possible. When the urgency of the new code outweighs the value of finishing the old work, choose immediate; for the vast majority of routine feature iterations, let the default deferral protect your users. That rule sounds simple written down, but at two in the morning during an incident it can save you several minutes of second-guessing.

What to test after switching

A changed default does not mean your application is automatically fine. The four checks below are worth running one by one on your first deploy after the switch. First, test an in-flight WebSocket: open a connection that uses the Hibernation API, send a few messages in it, then deploy, and check whether the connection is still alive and messages still flow. If it drops, check first whether you really use the Hibernation API, rather than blaming the platform.

Second, test an agent step mid-run: start a multi-step task, let it reach some middle step, then deploy, and see whether it finishes cleanly or gets reset; if it gets reset, check whether it resumes from the last step instead of starting over, or worse, repeating steps it already completed. This step tests your own idempotency and resumable-step design, not the platform's deferral feature.

Third, test the “deploy, then immediately call” case: send a request right after deploying and see whether it runs on old code or new code. That result decides how your post-deploy verification scripts, health checks, and smoke tests should be written. If a verification script assumes “right after deploy means new code” while the default is deferred, it may report a false failure on its first run, and the script needs to change to “verify after the object hibernates” — or that verification deploy should use immediate mode on its own.

Fourth, test the boundary of the delay itself: deliberately keep an object active past the default five minutes after a deploy, and confirm it resets and adopts new code as expected. That may seem counter-intuitive — why test the interruption case? Because you need to see the boundary behaviour with your own eyes, not just trust the happy path. Knowing when it will break matters more than knowing when it will not, since your user-facing messages, retry logic, and timeout settings all depend on it.

When choosing a delay length, one practical suggestion is worth adding: start with the default five minutes and do not rush to change the configuration. For many small projects, the problem is not that the delay is too short, but that the task itself cannot resume from a checkpoint. Run the four tests above first, observe how long your objects typically take to hibernate and whether a reset task can pick up where it left off, and only then decide whether to widen the delay to ten minutes or more. If tests show most objects hibernate within two or three minutes, the default five minutes is already plenty and changing the setting adds nothing; if tests show a long task keeps hitting the five-minute boundary before being reset, what needs fixing is not the delay number but how the task is split. Configuration should follow measurement, not gut feeling.

Once those four checks pass, your understanding moves from “read the news” to “verified it in my own project.” That is exactly the state vibe projects need most: not chasing every new feature, but landing the useful ones, testing them, and folding them into your own release habits. This Cloudflare change introduces no new concept and requires no rewrite; it simply changes the default from “interrupt immediately” to “wait if you can.” But defaults have the widest impact: every project that never configured this explicitly becomes a little gentler by default. And for projects running agents, chat rooms, and game state on Durable Objects, that little bit of gentleness may be the difference between a user who stays and a user who leaves.

Views 0Comments 0

Comments (0)

ME
0/1000
Loading comments...

Sources

Browse projectsPublish your project

Related articles