You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/docs/workers/configuration/versions-and-deployments/cohort-based-deployments.mdx
+153-1Lines changed: 153 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -271,10 +271,162 @@ If Worker A does not pass a cohort, Worker B falls back to its default version c
271
271
272
272
## Durable Objects
273
273
274
+
### Current behavior
275
+
274
276
:::warning
275
-
Cohort-based deployments do not affect [Durable Object](/durable-objects/) version routing. Durable Objects ignore the `Cloudflare-Workers-Cohort` header and follow the standard [gradual deployments behavior for Durable Objects](/workers/configuration/versions-and-deployments/gradual-deployments/#gradual-deployments-for-durable-objects).
277
+
Cohort-based deployments do not currently affect [Durable Object](/durable-objects/) version routing. Durable Objects ignore the `Cloudflare-Workers-Cohort` header and follow the standard [gradual deployments behavior for Durable Objects](/workers/configuration/versions-and-deployments/gradual-deployments/#gradual-deployments-for-durable-objects).
278
+
:::
279
+
280
+
With [gradual deployments](/workers/configuration/versions-and-deployments/gradual-deployments/#gradual-deployments-for-durable-objects), each Durable Object instance is assigned a version based on a hash of its unique ID and the deployment percentages. The assignment is deterministic and sticky -- the same instance stays on the same version until a new deployment is created. However, you have no control over which instances get which version.
This means you cannot say "I want all paid users' Durable Objects on the new version." The hash decides, and a high-value customer's Durable Object might end up on the untested version.
298
+
299
+
### Planned: Cohort-based version routing for Durable Objects
300
+
301
+
:::note
302
+
The following describes planned behavior that is not yet available. The API and behavior may change before release.
276
303
:::
277
304
305
+
Cohort-based deployments for Durable Objects will let you control which instances run which version based on your business logic. Instead of a random hash deciding, your Worker code explicitly assigns a cohort when obtaining a stub to a Durable Object instance.
306
+
307
+
#### How it will work
308
+
309
+
Your deployment configuration maps cohorts to versions, the same as for stateless Workers:
310
+
311
+
```txt
312
+
Deployment config:
313
+
cohort "free" → Version A (stable)
314
+
cohort "paid" → Version B (new features)
315
+
default (null) → Version A
316
+
```
317
+
318
+
Your Worker passes the cohort at `.get()` time -- when obtaining a [stub](/durable-objects/best-practices/access-durable-objects-from-a-worker/#2-create-durable-object-stubs) to a Durable Object, not when making an RPC call on it:
319
+
320
+
```ts
321
+
exportdefault {
322
+
async fetch(request:Request, env:Env) {
323
+
const userId =getUserId(request);
324
+
const plan =getUserPlan(request); // "free" or "paid"
325
+
326
+
const id =env.USER_DO.idFromName(userId);
327
+
328
+
// Pass the cohort when getting the stub
329
+
const stub =env.USER_DO.get(id, {
330
+
version: { cohort: plan }
331
+
});
332
+
333
+
// Make the RPC call -- no cohort here, the version is already decided
334
+
const result =awaitstub.getProfile();
335
+
returnResponse.json(result);
336
+
},
337
+
};
338
+
```
339
+
340
+
The Durable Object sees its cohort at runtime:
341
+
342
+
```ts
343
+
exportclassUserDOextendsDurableObject {
344
+
async getProfile() {
345
+
const myCohort =this.ctx.version.cohort; // "free" or "paid"
346
+
const myVersion =this.env.CF_VERSION_METADATA.id; // version UUID
347
+
348
+
return {
349
+
cohort: myCohort,
350
+
version: myVersion,
351
+
};
352
+
}
353
+
}
354
+
```
355
+
356
+
#### Version locking
357
+
358
+
A Durable Object instance locks to the version of the cohort it was instantiated with. If a subsequent request passes a different cohort, the instance stays on its original version. This prevents the Durable Object from flipping between code versions mid-lifetime, which would risk data corruption.
The cohort will be persisted so that when a Durable Object is [evicted](/durable-objects/concepts/durable-object-lifecycle/) from memory (due to inactivity or server maintenance) and later reinstantiated, it returns to the same cohort and version.
373
+
374
+
```txt
375
+
1. bob starts with cohort "paid" → Version B
376
+
Cohort "paid" is persisted.
377
+
378
+
2. bob is evicted (idle overnight).
379
+
Stored data and cohort persist.
380
+
381
+
3. New request arrives for bob.
382
+
System reads persisted cohort → "paid"
383
+
→ bob reinstantiates on Version B ✅
384
+
385
+
4. bob has a scheduled alarm that fires.
386
+
No incoming request, no caller cohort.
387
+
System reads persisted cohort → "paid"
388
+
→ bob runs on Version B ✅
389
+
```
390
+
391
+
This means not every caller needs to know the correct cohort. Once a Durable Object's cohort is set, it sticks until you change it or create a new deployment.
392
+
393
+
#### Cohort is optional
394
+
395
+
If you do not pass a cohort, the Durable Object uses the default version selection -- the same behavior as standard gradual deployments. Existing code that does not pass a cohort will continue to work without changes.
396
+
397
+
```ts
398
+
// No cohort -- uses default version selection (hash-based)
399
+
const stub =env.USER_DO.get(id);
400
+
401
+
// With cohort -- uses cohort-based version selection
The key difference from gradual deployments is the type of control you get over version assignment:
408
+
409
+
```txt
410
+
Gradual deployments (today):
411
+
"Roughly 40% of my DO instances will run the new code."
412
+
"I do not know which ones. The hash decides."
413
+
414
+
Cohort-based deployments (planned):
415
+
"All paid users' DOs run the new code."
416
+
"All free users' DOs stay on the stable code."
417
+
"I decide, based on my business logic, and it sticks."
418
+
```
419
+
420
+
With gradual deployments, you have **statistical** control -- "approximately this percentage." With cohort-based deployments, you have **semantic** control -- "these specific user segments." You can start with your lowest-risk instances, verify everything works, then move higher-value instances over deliberately.
0 commit comments