From 46e83013213bbf55916b0824c815f717c762b806 Mon Sep 17 00:00:00 2001 From: iglesiasbrandon <5313116+iglesiasbrandon@users.noreply.github.com> Date: Mon, 18 May 2026 16:16:59 -0400 Subject: [PATCH 1/4] [Durable Objects] Improve scanability of api/id.mdx name section - Break up the dense 'undefined' sentence into a bulleted list, and consolidate the newUniqueId() case into the same list for completeness. - Add a tip callout highlighting alarms as a primary use case for ctx.id.name (companion to the existing historical-caveat note). - Add an in-Durable-Object code example (JavaScript and Python) showing ctx.id.name in use, alongside the existing client-side examples. --- src/content/docs/durable-objects/api/id.mdx | 42 ++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/content/docs/durable-objects/api/id.mdx b/src/content/docs/durable-objects/api/id.mdx index 53f002be2f6f63c..48c105a4490003e 100644 --- a/src/content/docs/durable-objects/api/id.mdx +++ b/src/content/docs/durable-objects/api/id.mdx @@ -80,7 +80,15 @@ assert not id1.equals(id2), "Different unique ids should never be equal." `name` is an optional property of a `DurableObjectId`, which returns the name that was used to create the `DurableObjectId` via [`DurableObjectNamespace::idFromName`](/durable-objects/api/namespace/#idfromname). This value is undefined if the `DurableObjectId` was constructed using [`DurableObjectNamespace::newUniqueId`](/durable-objects/api/namespace/#newuniqueid). -The `name` property is available on `ctx.id` inside the Durable Object when the caller uses `idFromName()` or `getByName()`. If the caller accesses the Durable Object using `idFromString()`, `ctx.id.name` will be `undefined`, even if the ID was originally created with `idFromName()`. Names longer than 1,024 bytes are not passed through and will be `undefined` on `ctx.id`. +The `name` property is also available on `ctx.id` inside the Durable Object when the caller uses `idFromName()` or `getByName()`. `ctx.id.name` will be `undefined` in the following cases: + +- The caller accesses the Durable Object using `idFromString()`, even if the ID was originally created with `idFromName()`. +- Names longer than 1,024 bytes are not passed through to `ctx.id`. +- The Durable Object was created with `newUniqueId()`. + +:::tip[Useful for alarms] +`ctx.id.name` is especially useful inside [alarm handlers](/durable-objects/api/alarms/), where there is no calling client to pass the name as an argument. When the alarm fires, `ctx.id.name` holds the same name the object was originally accessed with. +::: :::note Alarms created before 2026-03-15 do not have `name` stored. When such an alarm fires, `ctx.id.name` will be `undefined`, and any new alarm scheduled from that handler will also lack a `name`. To fix this, reschedule the alarm from a `fetch()` or RPC handler where `name` is available. @@ -115,6 +123,38 @@ assert from_name_id.name == "foo", "name matches parameter to idFromName" +The same `name` is available inside the Durable Object via `ctx.id.name`: + + + + + +```js +import { DurableObject } from "cloudflare:workers"; + +export class ChatRoom extends DurableObject { + async getRoomName() { + return this.ctx.id.name; // "foo" when accessed via getByName("foo") + } +} +``` + + + + + +```python +from workers import DurableObject + +class ChatRoom(DurableObject): + async def get_room_name(self): + return self.ctx.id.name # "foo" when accessed via get_by_name("foo") +``` + + + + + ## Related resources - [Durable Objects: Easy, Fast, Correct – Choose Three](https://blog.cloudflare.com/durable-objects-easy-fast-correct-choose-three/). From 2058cf7152519e517ce0e672f05bc894bf24bda4 Mon Sep 17 00:00:00 2001 From: iglesiasbrandon <5313116+iglesiasbrandon@users.noreply.github.com> Date: Tue, 19 May 2026 13:32:10 -0400 Subject: [PATCH 2/4] [Durable Objects] Document jurisdiction property and ctx.id.jurisdiction availability --- ...6-05-18-durable-object-id-jurisdiction.mdx | 39 ++++++++++ src/content/docs/durable-objects/api/id.mdx | 78 +++++++++++++++++++ .../reference/data-location.mdx | 20 +++-- 3 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 src/content/changelog/durable-objects/2026-05-18-durable-object-id-jurisdiction.mdx diff --git a/src/content/changelog/durable-objects/2026-05-18-durable-object-id-jurisdiction.mdx b/src/content/changelog/durable-objects/2026-05-18-durable-object-id-jurisdiction.mdx new file mode 100644 index 000000000000000..e487c17fb79739a --- /dev/null +++ b/src/content/changelog/durable-objects/2026-05-18-durable-object-id-jurisdiction.mdx @@ -0,0 +1,39 @@ +--- +title: Access Durable Object jurisdiction via `ctx.id.jurisdiction` +description: Read the jurisdiction of a jurisdiction-restricted Durable Object from within the object itself. +products: + - durable-objects + - workers +date: 2026-05-18 +--- + +`ctx.id.jurisdiction` inside a Durable Object now reports the [jurisdiction](/durable-objects/reference/data-location/#restrict-durable-objects-to-a-jurisdiction) that the object was created in, matching the value seen client-side. If a Worker accesses a Durable Object through a jurisdiction-restricted namespace — for example `env.MY_DURABLE_OBJECT.jurisdiction("eu")` — the same jurisdiction is available on `ctx.id.jurisdiction` inside the object, so you can make region-aware decisions without passing the jurisdiction through method arguments or persisting it in storage. + +The `jurisdiction` property was previously gated behind an experimental flag because the value was not consistently available on the `DurableObjectId` exposed inside a Durable Object as `ctx.id`. With this change, `jurisdiction` is generally available and is preserved across every ID-construction path, including: + +- IDs created from a jurisdiction-restricted subnamespace, for example `env.MY_DURABLE_OBJECT.jurisdiction("eu").idFromName("foo")` or `.newUniqueId()`. +- IDs created via `env.MY_DURABLE_OBJECT.newUniqueId({ jurisdiction: "eu" })`. +- IDs restored from a string via `idFromString()`, including when restored through the unrestricted namespace binding. +- IDs observed inside [alarm handlers](/durable-objects/api/alarms/) for alarms scheduled on 2026-03-15 or later. + +```js +export class RegionalRoom extends DurableObject { + async fetch(request) { + // "eu" when accessed through env.MY_DURABLE_OBJECT.jurisdiction("eu") + const region = this.ctx.id.jurisdiction; + return new Response(`Hello from ${region ?? "the default region"}!`); + } +} + +// Worker +export default { + async fetch(request, env) { + const stub = env.MY_DURABLE_OBJECT.jurisdiction("eu").getByName("general"); + return stub.fetch(request); + }, +}; +``` + +`ctx.id.jurisdiction` is `undefined` for Durable Objects that were not created in a jurisdiction-restricted namespace. Alarms scheduled before 2026-03-15 also do not have `jurisdiction` stored; to backfill the value, reschedule the alarm from a `fetch()` or RPC handler. + +For more information, refer to the [Durable Object ID documentation](/durable-objects/api/id/#jurisdiction). diff --git a/src/content/docs/durable-objects/api/id.mdx b/src/content/docs/durable-objects/api/id.mdx index 48c105a4490003e..b48bfda45ee3118 100644 --- a/src/content/docs/durable-objects/api/id.mdx +++ b/src/content/docs/durable-objects/api/id.mdx @@ -155,6 +155,84 @@ class ChatRoom(DurableObject): +### `jurisdiction` + +`jurisdiction` is an optional property of a `DurableObjectId`, which returns the [jurisdiction](/durable-objects/reference/data-location/#restrict-durable-objects-to-a-jurisdiction) the ID is restricted to, such as `"eu"` or `"fedramp"`. This value is `undefined` if the `DurableObjectId` was created from a namespace that is not restricted to a jurisdiction. + +The `jurisdiction` property is also available on `ctx.id` inside the Durable Object. Unlike `name`, the jurisdiction is preserved across every ID-construction path: + +- **Populated** when the ID is created from a jurisdiction-restricted subnamespace returned by `env.MY_DURABLE_OBJECT.jurisdiction("eu")` — for example via `.idFromName("foo")` or `.newUniqueId()`. +- **Populated** when the ID is created with `env.MY_DURABLE_OBJECT.newUniqueId({ jurisdiction: "eu" })`. +- **Populated** after a round-trip through `toString()` and `idFromString()`, including when the ID is restored through the non-restricted namespace binding. +- **Populated** inside [alarm handlers](/durable-objects/api/alarms/) for alarms scheduled on 2026-03-15 or later. +- **`undefined`** for Durable Objects created in a namespace that is not restricted to a jurisdiction. + +:::tip[Useful for region-aware logic] +Because `ctx.id.jurisdiction` is available inside the Durable Object — including in `alarm()` handlers and after restoring an ID from a string — you can use it to make region-aware decisions without passing the jurisdiction as an argument or persisting it in storage. +::: + +:::note +Alarms created before 2026-03-15 do not have `jurisdiction` stored. When such an alarm fires, `ctx.id.jurisdiction` will be `undefined`, and any new alarm scheduled from that handler will also lack a `jurisdiction`. To fix this, reschedule the alarm from a `fetch()` or RPC handler where `jurisdiction` is available. +::: + + + + + +```js +const plainId = env.MY_DURABLE_OBJECT.idFromName("foo"); +const euId = env.MY_DURABLE_OBJECT.jurisdiction("eu").idFromName("foo"); +console.assert(plainId.jurisdiction === undefined, "no jurisdiction set"); +console.assert(euId.jurisdiction === "eu", "jurisdiction matches namespace"); +``` + + + + + +```python +plain_id = env.MY_DURABLE_OBJECT.idFromName("foo") +eu_id = env.MY_DURABLE_OBJECT.jurisdiction("eu").idFromName("foo") +assert plain_id.jurisdiction is None, "no jurisdiction set" +assert eu_id.jurisdiction == "eu", "jurisdiction matches namespace" +``` + + + + + +The same `jurisdiction` is available inside the Durable Object via `ctx.id.jurisdiction`: + + + + + +```js +import { DurableObject } from "cloudflare:workers"; + +export class RegionalRoom extends DurableObject { + async getRegion() { + return this.ctx.id.jurisdiction; // "eu" when created via .jurisdiction("eu") + } +} +``` + + + + + +```python +from workers import DurableObject + +class RegionalRoom(DurableObject): + async def get_region(self): + return self.ctx.id.jurisdiction # "eu" when created via .jurisdiction("eu") +``` + + + + + ## Related resources - [Durable Objects: Easy, Fast, Correct – Choose Three](https://blog.cloudflare.com/durable-objects-easy-fast-correct-choose-three/). diff --git a/src/content/docs/durable-objects/reference/data-location.mdx b/src/content/docs/durable-objects/reference/data-location.mdx index 4f4ced530d3685f..2b50b4aa293d5db 100644 --- a/src/content/docs/durable-objects/reference/data-location.mdx +++ b/src/content/docs/durable-objects/reference/data-location.mdx @@ -58,11 +58,15 @@ Note that it is also possible to specify a jurisdiction by creating an individua ### Supported locations -| Parameter | Location | -| --------- | ---------------------------- | -| eu | The European Union | +| Parameter | Location | +| --------- | ------------------------------ | +| eu | The European Union | | fedramp | FedRAMP-compliant data centers | +### Read the jurisdiction from inside a Durable Object + +The jurisdiction of a Durable Object is available inside the object via [`ctx.id.jurisdiction`](/durable-objects/api/id/#jurisdiction). The value is preserved across `toString()` and `idFromString()` round-trips and is also available inside [alarm handlers](/durable-objects/api/alarms/) for alarms scheduled on 2026-03-15 or later, which makes it suitable for region-aware logic inside the Durable Object. + ## Provide a location hint Durable Objects, as with any stateful API, will often add response latency as requests must be forwarded to the data center where the Durable Object, or state, is located. @@ -102,10 +106,14 @@ Hints are a best effort and not a guarantee. Unlike with jurisdictions, Durable | afr | Africa 2 | | me | Middle East 2 | -1 Dynamic relocation of existing Durable Objects is planned for the future. +1 Dynamic relocation of existing Durable Objects is planned for the +future. -2 Durable Objects currently do not spawn in this location. Instead, the Durable Object will spawn in a nearby location which does support Durable Objects. For example, Durable Objects hinted to South America spawn in Eastern North America instead. +2 Durable Objects currently do not spawn in this location. Instead, +the Durable Object will spawn in a nearby location which does support Durable +Objects. For example, Durable Objects hinted to South America spawn in Eastern +North America instead. ## Additional resources -- You can find our more about where Durable Objects are located using the website: [Where Durable Objects Live](https://where.durableobjects.live/). \ No newline at end of file +- You can find our more about where Durable Objects are located using the website: [Where Durable Objects Live](https://where.durableobjects.live/). From cff8004e1cb74e723d51d3723c486dfab2dcba5b Mon Sep 17 00:00:00 2001 From: iglesiasbrandon <5313116+iglesiasbrandon@users.noreply.github.com> Date: Tue, 19 May 2026 13:40:36 -0400 Subject: [PATCH 3/4] [Durable Objects] Correct jurisdiction changelog date to feature rollout date --- ...iction.mdx => 2026-03-26-durable-object-id-jurisdiction.mdx} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/content/changelog/durable-objects/{2026-05-18-durable-object-id-jurisdiction.mdx => 2026-03-26-durable-object-id-jurisdiction.mdx} (99%) diff --git a/src/content/changelog/durable-objects/2026-05-18-durable-object-id-jurisdiction.mdx b/src/content/changelog/durable-objects/2026-03-26-durable-object-id-jurisdiction.mdx similarity index 99% rename from src/content/changelog/durable-objects/2026-05-18-durable-object-id-jurisdiction.mdx rename to src/content/changelog/durable-objects/2026-03-26-durable-object-id-jurisdiction.mdx index e487c17fb79739a..e53fbb06f3cb673 100644 --- a/src/content/changelog/durable-objects/2026-05-18-durable-object-id-jurisdiction.mdx +++ b/src/content/changelog/durable-objects/2026-03-26-durable-object-id-jurisdiction.mdx @@ -4,7 +4,7 @@ description: Read the jurisdiction of a jurisdiction-restricted Durable Object f products: - durable-objects - workers -date: 2026-05-18 +date: 2026-03-26 --- `ctx.id.jurisdiction` inside a Durable Object now reports the [jurisdiction](/durable-objects/reference/data-location/#restrict-durable-objects-to-a-jurisdiction) that the object was created in, matching the value seen client-side. If a Worker accesses a Durable Object through a jurisdiction-restricted namespace — for example `env.MY_DURABLE_OBJECT.jurisdiction("eu")` — the same jurisdiction is available on `ctx.id.jurisdiction` inside the object, so you can make region-aware decisions without passing the jurisdiction through method arguments or persisting it in storage. From 93f3c613ca3bc287cce2eb867fbc708fd41e727b Mon Sep 17 00:00:00 2001 From: iglesiasbrandon <5313116+iglesiasbrandon@users.noreply.github.com> Date: Wed, 20 May 2026 09:59:52 -0400 Subject: [PATCH 4/4] [Durable Objects] Address Max's review feedback on jurisdiction docs - Changelog: drop experimental flag framing; clarify idFromString bullet - id.mdx: invert 'jurisdiction' section framing to lead with availability and enumerate only the two undefined cases --- ...6-03-26-durable-object-id-jurisdiction.mdx | 4 +- src/content/docs/durable-objects/api/id.mdx | 51 ++----------------- 2 files changed, 6 insertions(+), 49 deletions(-) diff --git a/src/content/changelog/durable-objects/2026-03-26-durable-object-id-jurisdiction.mdx b/src/content/changelog/durable-objects/2026-03-26-durable-object-id-jurisdiction.mdx index e53fbb06f3cb673..a9a773b54a927f2 100644 --- a/src/content/changelog/durable-objects/2026-03-26-durable-object-id-jurisdiction.mdx +++ b/src/content/changelog/durable-objects/2026-03-26-durable-object-id-jurisdiction.mdx @@ -9,11 +9,11 @@ date: 2026-03-26 `ctx.id.jurisdiction` inside a Durable Object now reports the [jurisdiction](/durable-objects/reference/data-location/#restrict-durable-objects-to-a-jurisdiction) that the object was created in, matching the value seen client-side. If a Worker accesses a Durable Object through a jurisdiction-restricted namespace — for example `env.MY_DURABLE_OBJECT.jurisdiction("eu")` — the same jurisdiction is available on `ctx.id.jurisdiction` inside the object, so you can make region-aware decisions without passing the jurisdiction through method arguments or persisting it in storage. -The `jurisdiction` property was previously gated behind an experimental flag because the value was not consistently available on the `DurableObjectId` exposed inside a Durable Object as `ctx.id`. With this change, `jurisdiction` is generally available and is preserved across every ID-construction path, including: +`jurisdiction` is preserved across every ID-construction path, including: - IDs created from a jurisdiction-restricted subnamespace, for example `env.MY_DURABLE_OBJECT.jurisdiction("eu").idFromName("foo")` or `.newUniqueId()`. - IDs created via `env.MY_DURABLE_OBJECT.newUniqueId({ jurisdiction: "eu" })`. -- IDs restored from a string via `idFromString()`, including when restored through the unrestricted namespace binding. +- IDs restored from a string via `idFromString()` — the jurisdiction is encoded in the string itself, so it works on any namespace binding. - IDs observed inside [alarm handlers](/durable-objects/api/alarms/) for alarms scheduled on 2026-03-15 or later. ```js diff --git a/src/content/docs/durable-objects/api/id.mdx b/src/content/docs/durable-objects/api/id.mdx index b48bfda45ee3118..ed3f1d20ecca1d5 100644 --- a/src/content/docs/durable-objects/api/id.mdx +++ b/src/content/docs/durable-objects/api/id.mdx @@ -157,23 +157,12 @@ class ChatRoom(DurableObject): ### `jurisdiction` -`jurisdiction` is an optional property of a `DurableObjectId`, which returns the [jurisdiction](/durable-objects/reference/data-location/#restrict-durable-objects-to-a-jurisdiction) the ID is restricted to, such as `"eu"` or `"fedramp"`. This value is `undefined` if the `DurableObjectId` was created from a namespace that is not restricted to a jurisdiction. +`jurisdiction` is an optional property of a `DurableObjectId`, which returns the [jurisdiction](/durable-objects/reference/data-location/#restrict-durable-objects-to-a-jurisdiction) the ID is restricted to, such as `"eu"` or `"fedramp"`. The same value is available inside the Durable Object via `ctx.id.jurisdiction`, including in [alarm handlers](/durable-objects/api/alarms/) and after restoring an ID via `idFromString()`, so you can make region-aware decisions without passing the jurisdiction as an argument or persisting it in storage. -The `jurisdiction` property is also available on `ctx.id` inside the Durable Object. Unlike `name`, the jurisdiction is preserved across every ID-construction path: +`ctx.id.jurisdiction` is `undefined` in two cases: -- **Populated** when the ID is created from a jurisdiction-restricted subnamespace returned by `env.MY_DURABLE_OBJECT.jurisdiction("eu")` — for example via `.idFromName("foo")` or `.newUniqueId()`. -- **Populated** when the ID is created with `env.MY_DURABLE_OBJECT.newUniqueId({ jurisdiction: "eu" })`. -- **Populated** after a round-trip through `toString()` and `idFromString()`, including when the ID is restored through the non-restricted namespace binding. -- **Populated** inside [alarm handlers](/durable-objects/api/alarms/) for alarms scheduled on 2026-03-15 or later. -- **`undefined`** for Durable Objects created in a namespace that is not restricted to a jurisdiction. - -:::tip[Useful for region-aware logic] -Because `ctx.id.jurisdiction` is available inside the Durable Object — including in `alarm()` handlers and after restoring an ID from a string — you can use it to make region-aware decisions without passing the jurisdiction as an argument or persisting it in storage. -::: - -:::note -Alarms created before 2026-03-15 do not have `jurisdiction` stored. When such an alarm fires, `ctx.id.jurisdiction` will be `undefined`, and any new alarm scheduled from that handler will also lack a `jurisdiction`. To fix this, reschedule the alarm from a `fetch()` or RPC handler where `jurisdiction` is available. -::: +- The Durable Object was not created in a jurisdiction-restricted namespace. +- The Durable Object's alarm was scheduled before 2026-03-15. To backfill the value, reschedule the alarm from a `fetch()` or RPC handler. @@ -201,38 +190,6 @@ assert eu_id.jurisdiction == "eu", "jurisdiction matches namespace" -The same `jurisdiction` is available inside the Durable Object via `ctx.id.jurisdiction`: - - - - - -```js -import { DurableObject } from "cloudflare:workers"; - -export class RegionalRoom extends DurableObject { - async getRegion() { - return this.ctx.id.jurisdiction; // "eu" when created via .jurisdiction("eu") - } -} -``` - - - - - -```python -from workers import DurableObject - -class RegionalRoom(DurableObject): - async def get_region(self): - return self.ctx.id.jurisdiction # "eu" when created via .jurisdiction("eu") -``` - - - - - ## Related resources - [Durable Objects: Easy, Fast, Correct – Choose Three](https://blog.cloudflare.com/durable-objects-easy-fast-correct-choose-three/).