From 2fa885e3b11e059ee7b07d64099e4c66bf73fec2 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Thu, 16 Jul 2026 18:06:27 -0700 Subject: [PATCH 01/54] Add self-hosted Nexus guidance for Global Namespace failover Documents how Nexus Operation completion callbacks behave when a Global Namespace fails over between clusters, and the configuration required for worker-target endpoints: endpoint registry parity, replicated Namespaces, auto-forwarding, and a frontend httpPort plus advertised httpAddress on every cluster. Reorders "Build and use Nexus Services" above the new section. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 92 +++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 95e78a2e14..4cc369106b 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -2,13 +2,14 @@ id: nexus title: Self-hosted Temporal Nexus sidebar_label: Temporal Nexus -description: Use Nexus in your self-hosted Temporal Service. +description: Use Nexus in your self-hosted Temporal Service, including across Global (multi-region) Namespaces and failover. toc_max_heading_level: 4 keywords: - self-hosted tags: - Self hosting - enable-nexus + - global-namespace --- :::info NEW TO NEXUS? @@ -21,11 +22,6 @@ This page explains how to self-host Nexus. To learn about Nexus, see the [how Ne Nexus can be configured by setting static configuration and dynamic configuration entries. - -:::note -Nexus is supported in single-cluster setups only. See [Nexus Architecture](https://github.com/temporalio/temporal/blob/main/docs/architecture/nexus.md) for operational details. -::: - :::note Replace `$PUBLIC_URL` with a URL value that's accessible to external callers or internally within the cluster. Currently, external Nexus calls are considered experimental so it should be safe to use the address of an internal load balancer for the Frontend Service. @@ -91,3 +87,87 @@ See [how Nexus works](/nexus) for an architectural overview, then follow an SDK [.NET](/develop/dotnet/nexus) ::: + +## Global Namespaces (multi-region failover) + +Nexus works across a [Global (multi-region) Namespace](/global-namespace): an +asynchronous operation started in one region completes even if the Namespace fails +over or the region is lost before it finishes. This applies to +[worker-target endpoints](/nexus/endpoints) — the endpoint routes to a target +Namespace and Task Queue a Temporal worker polls. + +### Configuration + +1. **Register the endpoint in every region.** The + [Nexus Endpoint registry](/nexus/registry) is not replicated across clusters; + create the same endpoint (same target Namespace and task queue) on each cluster. + +2. **Make both Namespaces Global Namespaces** replicated across the same clusters — + the one that *calls* the operation and the one that *handles* it — so every + cluster is aware of both. See + [multi-cluster replication](/self-hosted-guide/multi-cluster-replication) for + connecting clusters and creating replicated Namespaces. + +3. **Give every cluster a frontend HTTP address — set *and* advertised.** Each + cluster must set a local `frontend.rpc.httpPort` **and** advertise it via + `clusterMetadata.clusterInformation..httpAddress`. This is the same + `httpAddress` shown in [Enable Nexus](#enable-nexus) — but for failover it must + be set on **every** cluster, each with its own address, not just one. Callback + routing resolves this address at delivery time; without it, cross-cluster + callbacks fail with `HTTPAddress not configured for cluster: `. The + `operator cluster upsert` flow does **not** set `httpAddress` — configure it + explicitly, and re-run `upsert` after changing it. + + ```yaml + # cluster-a (repeat on every cluster with its own addresses) + services: + frontend: + rpc: + httpPort: 7243 + clusterMetadata: + clusterInformation: + cluster-a: + rpcAddress: "cluster-a-host:7233" + httpAddress: "cluster-a-host:7243" # advertised to peers — required + ``` + +4. **Enable auto-forwarding** (per Namespace) so a request that lands on a standby + cluster is forwarded to the active one, with the frontend `dcRedirectionPolicy` + allowing redirection (e.g. `all-apis-forwarding`). + + ```yaml + system.enableNamespaceNotActiveAutoForwarding: + - value: true + ``` + +5. **Leave `component.nexusoperations.useSystemCallbackURL` at its default (`true`).** + Callbacks then route internally; no callback URL is required. + +### What to expect on failover + +```mermaid +%%{init: {'sequence': {'mirrorActors': false}}}%% +sequenceDiagram + participant C as Caller (client ns) + participant A as Region A + participant B as Region B + C->>A: start async Nexus operation + A-->>C: operation started, token + Note over A,B: region A fails over / is lost — active moves to B + A->>B: handler workflow + callback resume on B + B->>C: completion delivered to the caller's active cluster + Note over C: caller workflow completes +``` + +- **Completion callbacks are delivered internally** to the caller Namespace's + *current* active cluster, re-resolved on each attempt — no callback URL, DNS, or + routing layer to manage. +- **Forwarding runs on the surviving cluster**, toward the active cluster; it does + **not** depend on the failed region. Planned failover and **permanent region + loss** both work. +- **On permanent region loss, fail over *every* Namespace off the dead region** + (both caller and handler). A completion whose caller Namespace still points at the + lost region retries until you do. +- **Caveat:** anything not replicated before a region dies is lost. Long-running + async operations replicate their setup state early, so mid-flight failover + completes. From 4ac3d8279283012cd676b19d5db7a02fcae67dae Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 07:49:00 -0700 Subject: [PATCH 02/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 4cc369106b..8efe09d106 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -98,16 +98,14 @@ Namespace and Task Queue a Temporal worker polls. ### Configuration -1. **Register the endpoint in every region.** The - [Nexus Endpoint registry](/nexus/registry) is not replicated across clusters; - create the same endpoint (same target Namespace and task queue) on each cluster. - -2. **Make both Namespaces Global Namespaces** replicated across the same clusters — - the one that *calls* the operation and the one that *handles* it — so every - cluster is aware of both. See +1. **Setup Multi-Cluster Replication** See [multi-cluster replication](/self-hosted-guide/multi-cluster-replication) for connecting clusters and creating replicated Namespaces. +2. **Register endpoints in every region.** The + [Nexus Endpoint registry](/nexus/registry) is not replicated across clusters. + Create the same endpoints (same target Namespace and task queue) on each cluster. + 3. **Give every cluster a frontend HTTP address — set *and* advertised.** Each cluster must set a local `frontend.rpc.httpPort` **and** advertise it via `clusterMetadata.clusterInformation..httpAddress`. This is the same @@ -140,9 +138,6 @@ Namespace and Task Queue a Temporal worker polls. - value: true ``` -5. **Leave `component.nexusoperations.useSystemCallbackURL` at its default (`true`).** - Callbacks then route internally; no callback URL is required. - ### What to expect on failover ```mermaid From 5cab21140d3285f7888d0b9ac03ab62de7a2f28a Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 07:52:28 -0700 Subject: [PATCH 03/54] Apply docs style pass and note split-active-Cluster failover - Capitalize Temporal proper nouns (Cluster, Namespace, Workflow, Worker, Task Queue, Endpoint, Nexus Operation) to match sibling multi-cluster docs. - Replace em-dashes with plain punctuation; drop "e.g."/"via" per style guide. - Add that caller and handler Namespaces can be active on different Clusters (per-Namespace active cluster), so cross-Cluster completion forwarding is a steady state, handled automatically once httpAddress is advertised. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 87 ++++++++++--------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 8efe09d106..190d30203e 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -91,33 +91,33 @@ See [how Nexus works](/nexus) for an architectural overview, then follow an SDK ## Global Namespaces (multi-region failover) Nexus works across a [Global (multi-region) Namespace](/global-namespace): an -asynchronous operation started in one region completes even if the Namespace fails -over or the region is lost before it finishes. This applies to -[worker-target endpoints](/nexus/endpoints) — the endpoint routes to a target -Namespace and Task Queue a Temporal worker polls. +asynchronous Nexus Operation started in one Cluster completes even if the Namespace +fails over, or its Cluster is lost, before the Operation finishes. This applies to +[worker-target Endpoints](/nexus/endpoints), where the Endpoint routes to a target +Namespace and Task Queue that a Worker polls. ### Configuration -1. **Setup Multi-Cluster Replication** See - [multi-cluster replication](/self-hosted-guide/multi-cluster-replication) for - connecting clusters and creating replicated Namespaces. +1. **Set up Multi-Cluster Replication.** See + [Multi-Cluster Replication](/self-hosted-guide/multi-cluster-replication) for + connecting Clusters and creating replicated Namespaces. -2. **Register endpoints in every region.** The - [Nexus Endpoint registry](/nexus/registry) is not replicated across clusters. - Create the same endpoints (same target Namespace and task queue) on each cluster. +2. **Register Endpoints on every Cluster.** The + [Nexus Endpoint registry](/nexus/registry) is not replicated across Clusters. + Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. -3. **Give every cluster a frontend HTTP address — set *and* advertised.** Each - cluster must set a local `frontend.rpc.httpPort` **and** advertise it via +3. **Give every Cluster a frontend HTTP address, set *and* advertised.** Each + Cluster must set a local `frontend.rpc.httpPort` and advertise it through `clusterMetadata.clusterInformation..httpAddress`. This is the same - `httpAddress` shown in [Enable Nexus](#enable-nexus) — but for failover it must - be set on **every** cluster, each with its own address, not just one. Callback - routing resolves this address at delivery time; without it, cross-cluster - callbacks fail with `HTTPAddress not configured for cluster: `. The - `operator cluster upsert` flow does **not** set `httpAddress` — configure it - explicitly, and re-run `upsert` after changing it. + `httpAddress` shown in [Enable Nexus](#enable-nexus), but for failover you set it + on **every** Cluster, each with its own address. Callback routing resolves this + address at delivery time. Without it, cross-Cluster callbacks fail with + `HTTPAddress not configured for cluster: `. The `operator cluster upsert` + command does not set `httpAddress`, so configure it explicitly and re-run + `upsert` after changing it. ```yaml - # cluster-a (repeat on every cluster with its own addresses) + # cluster-a (repeat on every Cluster with its own addresses) services: frontend: rpc: @@ -126,12 +126,12 @@ Namespace and Task Queue a Temporal worker polls. clusterInformation: cluster-a: rpcAddress: "cluster-a-host:7233" - httpAddress: "cluster-a-host:7243" # advertised to peers — required + httpAddress: "cluster-a-host:7243" # advertised to peers, required ``` 4. **Enable auto-forwarding** (per Namespace) so a request that lands on a standby - cluster is forwarded to the active one, with the frontend `dcRedirectionPolicy` - allowing redirection (e.g. `all-apis-forwarding`). + Cluster forwards to the active one, with the frontend `dcRedirectionPolicy` set + to allow redirection (for example, `all-apis-forwarding`). ```yaml system.enableNamespaceNotActiveAutoForwarding: @@ -143,26 +143,31 @@ Namespace and Task Queue a Temporal worker polls. ```mermaid %%{init: {'sequence': {'mirrorActors': false}}}%% sequenceDiagram - participant C as Caller (client ns) - participant A as Region A - participant B as Region B - C->>A: start async Nexus operation - A-->>C: operation started, token - Note over A,B: region A fails over / is lost — active moves to B - A->>B: handler workflow + callback resume on B - B->>C: completion delivered to the caller's active cluster - Note over C: caller workflow completes + participant C as Caller Namespace + participant A as Cluster A + participant B as Cluster B + C->>A: start async Nexus Operation + A-->>C: Operation started, token returned + Note over A,B: Cluster A fails over or is lost, active moves to B + A->>B: handler Workflow and callback resume on B + B->>C: completion delivered to the caller's active Cluster + Note over C: caller Workflow completes ``` - **Completion callbacks are delivered internally** to the caller Namespace's - *current* active cluster, re-resolved on each attempt — no callback URL, DNS, or - routing layer to manage. -- **Forwarding runs on the surviving cluster**, toward the active cluster; it does - **not** depend on the failed region. Planned failover and **permanent region - loss** both work. -- **On permanent region loss, fail over *every* Namespace off the dead region** + current active Cluster, re-resolved on each attempt. There is no callback URL, + DNS, or routing layer to manage. +- **Forwarding runs on the surviving Cluster**, toward the active Cluster. It does + not depend on the failed Cluster, so planned failover and permanent Cluster loss + both work. +- **The caller and handler can be active on different Clusters.** The active + Cluster is set per Namespace, so the caller Namespace can be active on one Cluster + while the handler Namespace is active on another. The completion is then forwarded + across Clusters automatically, as long as each Cluster advertises its + `httpAddress` (requirement 3). +- **On permanent Cluster loss, fail over *every* Namespace off the lost Cluster** (both caller and handler). A completion whose caller Namespace still points at the - lost region retries until you do. -- **Caveat:** anything not replicated before a region dies is lost. Long-running - async operations replicate their setup state early, so mid-flight failover - completes. + lost Cluster retries until you do. +- **Caveat:** anything not replicated before a Cluster is lost is lost with it. + Long-running Operations replicate their setup state early, so a mid-flight + failover completes. From 81c5e94326d405a616b7136c19d0821e63d0bd06 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 08:05:44 -0700 Subject: [PATCH 04/54] Refine failover section: target-types note and Vale fixes - Move the target-type scope into a note that also mentions external-target Endpoints (--target-url) for completeness. - Vale pass: fix Worker casing, use contractions, split the long intro sentence, and use "automatic forwarding" instead of "auto-forwarding". Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 190d30203e..58be002953 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -90,11 +90,17 @@ See [how Nexus works](/nexus) for an architectural overview, then follow an SDK ## Global Namespaces (multi-region failover) -Nexus works across a [Global (multi-region) Namespace](/global-namespace): an +Nexus works across a [Global (multi-region) Namespace](/global-namespace). An asynchronous Nexus Operation started in one Cluster completes even if the Namespace -fails over, or its Cluster is lost, before the Operation finishes. This applies to -[worker-target Endpoints](/nexus/endpoints), where the Endpoint routes to a target -Namespace and Task Queue that a Worker polls. +fails over, or its Cluster is lost, before the Operation finishes. + +:::note Endpoint target types + +This applies to [Worker-target Endpoints](/nexus/endpoints), where the Endpoint +routes to a target Namespace and Task Queue that a Worker polls. Endpoints can also +target an external URL (`--target-url`), which is experimental and not covered here. + +::: ### Configuration @@ -103,7 +109,7 @@ Namespace and Task Queue that a Worker polls. connecting Clusters and creating replicated Namespaces. 2. **Register Endpoints on every Cluster.** The - [Nexus Endpoint registry](/nexus/registry) is not replicated across Clusters. + [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. 3. **Give every Cluster a frontend HTTP address, set *and* advertised.** Each @@ -113,7 +119,7 @@ Namespace and Task Queue that a Worker polls. on **every** Cluster, each with its own address. Callback routing resolves this address at delivery time. Without it, cross-Cluster callbacks fail with `HTTPAddress not configured for cluster: `. The `operator cluster upsert` - command does not set `httpAddress`, so configure it explicitly and re-run + command doesn't set `httpAddress`, so configure it explicitly and re-run `upsert` after changing it. ```yaml @@ -129,9 +135,9 @@ Namespace and Task Queue that a Worker polls. httpAddress: "cluster-a-host:7243" # advertised to peers, required ``` -4. **Enable auto-forwarding** (per Namespace) so a request that lands on a standby - Cluster forwards to the active one, with the frontend `dcRedirectionPolicy` set - to allow redirection (for example, `all-apis-forwarding`). +4. **Enable automatic forwarding** (per Namespace) so a request that lands on a + standby Cluster forwards to the active one, with the frontend + `dcRedirectionPolicy` set to allow redirection (for example, `all-apis-forwarding`). ```yaml system.enableNamespaceNotActiveAutoForwarding: From 16a8c65de72669bfba127ad73b008ccc9006c5ef Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 08:15:39 -0700 Subject: [PATCH 05/54] Clarify forwarding config and avoid duplicating Multi-Cluster Replication - Split auto-forwarding into its two required parts: the static dcRedirectionPolicy (defaults to no redirection) and the per-Namespace system.enableNamespaceNotActiveAutoForwarding dynamic config. - Trim the httpAddress step to the Nexus-specific delta (httpPort + httpAddress) and defer base clusterMetadata/rpcAddress setup to the Multi-Cluster Replication page it links to. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 58be002953..9a46123e1d 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -112,32 +112,39 @@ target an external URL (`--target-url`), which is experimental and not covered h [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. -3. **Give every Cluster a frontend HTTP address, set *and* advertised.** Each - Cluster must set a local `frontend.rpc.httpPort` and advertise it through - `clusterMetadata.clusterInformation..httpAddress`. This is the same - `httpAddress` shown in [Enable Nexus](#enable-nexus), but for failover you set it - on **every** Cluster, each with its own address. Callback routing resolves this - address at delivery time. Without it, cross-Cluster callbacks fail with +3. **Advertise a frontend HTTP address on every Cluster.** On top of the + `clusterMetadata` you configured for replication, each Cluster must set a local + `frontend.rpc.httpPort` and add an `httpAddress` to its `clusterInformation` + entry so peers can reach it. Callback routing resolves this address at delivery + time. Without it, cross-Cluster callbacks fail with `HTTPAddress not configured for cluster: `. The `operator cluster upsert` command doesn't set `httpAddress`, so configure it explicitly and re-run `upsert` after changing it. ```yaml - # cluster-a (repeat on every Cluster with its own addresses) services: frontend: rpc: httpPort: 7243 clusterMetadata: clusterInformation: - cluster-a: - rpcAddress: "cluster-a-host:7233" - httpAddress: "cluster-a-host:7243" # advertised to peers, required + cluster-a: # existing replication entry, per Cluster + httpAddress: "cluster-a-host:7243" # add this, advertised to peers ``` -4. **Enable automatic forwarding** (per Namespace) so a request that lands on a - standby Cluster forwards to the active one, with the frontend - `dcRedirectionPolicy` set to allow redirection (for example, `all-apis-forwarding`). +4. **Enable automatic forwarding** so a request that lands on a standby Cluster + forwards to the active one. This has two parts. + + Set the server's `dcRedirectionPolicy` in static config. It defaults to no + redirection, so you must set it to `all-apis-forwarding` (or + `selected-apis-forwarding`): + + ```yaml + dcRedirectionPolicy: + policy: "all-apis-forwarding" + ``` + + Turn on auto-forwarding per Namespace in dynamic config: ```yaml system.enableNamespaceNotActiveAutoForwarding: From f8db375e238b79277c30d4e1af36805d37f4bddc Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:24:49 -0700 Subject: [PATCH 06/54] Link dcRedirectionPolicy to config reference; clarify clusterInformation entry - Link dcRedirectionPolicy to references/configuration, its canonical entry. - Clarify that the per-Cluster clusterInformation entry already contains the replication fields (enabled, rpcName, rpcAddress, initialFailoverVersion) and that httpAddress is added to it. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 9a46123e1d..1647630ac9 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -128,16 +128,18 @@ target an external URL (`--target-url`), which is experimental and not covered h httpPort: 7243 clusterMetadata: clusterInformation: - cluster-a: # existing replication entry, per Cluster + cluster-a: # per-Cluster entry from replication setup + # ...existing fields: enabled, rpcName, rpcAddress, initialFailoverVersion httpAddress: "cluster-a-host:7243" # add this, advertised to peers ``` 4. **Enable automatic forwarding** so a request that lands on a standby Cluster forwards to the active one. This has two parts. - Set the server's `dcRedirectionPolicy` in static config. It defaults to no - redirection, so you must set it to `all-apis-forwarding` (or - `selected-apis-forwarding`): + Set the server's + [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) in static + config. It defaults to no redirection, so you must set it to + `all-apis-forwarding` (or `selected-apis-forwarding`): ```yaml dcRedirectionPolicy: From b9b66c8a52e22bd1f2b1215268da215efb59a2d1 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:26:42 -0700 Subject: [PATCH 07/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 1647630ac9..06c1233893 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -128,7 +128,7 @@ target an external URL (`--target-url`), which is experimental and not covered h httpPort: 7243 clusterMetadata: clusterInformation: - cluster-a: # per-Cluster entry from replication setup + cluster-a: # ...existing fields: enabled, rpcName, rpcAddress, initialFailoverVersion httpAddress: "cluster-a-host:7243" # add this, advertised to peers ``` From f0dfd7ef08381067647baa68762864f8cd9c6f06 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:36:49 -0700 Subject: [PATCH 08/54] De-duplicate httpAddress step against Enable Nexus Step 3 repeated the httpPort/httpAddress config already shown in Enable Nexus. Reference that section and keep only the multi-cluster delta: set them on every Cluster, plus the operator cluster upsert caveat. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 06c1233893..e3891cc1cc 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -112,26 +112,14 @@ target an external URL (`--target-url`), which is experimental and not covered h [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. -3. **Advertise a frontend HTTP address on every Cluster.** On top of the - `clusterMetadata` you configured for replication, each Cluster must set a local - `frontend.rpc.httpPort` and add an `httpAddress` to its `clusterInformation` - entry so peers can reach it. Callback routing resolves this address at delivery +3. **Advertise a frontend HTTP address on every Cluster.** [Enable Nexus](#enable-nexus) + sets `frontend.rpc.httpPort` and a `clusterInformation..httpAddress` for + one Cluster. For failover, set them on **every** Cluster, each with its own + address, so peers can reach it. Callback routing resolves this address at delivery time. Without it, cross-Cluster callbacks fail with `HTTPAddress not configured for cluster: `. The `operator cluster upsert` - command doesn't set `httpAddress`, so configure it explicitly and re-run - `upsert` after changing it. - - ```yaml - services: - frontend: - rpc: - httpPort: 7243 - clusterMetadata: - clusterInformation: - cluster-a: - # ...existing fields: enabled, rpcName, rpcAddress, initialFailoverVersion - httpAddress: "cluster-a-host:7243" # add this, advertised to peers - ``` + command doesn't set `httpAddress`, so configure it explicitly and re-run `upsert` + after changing it. 4. **Enable automatic forwarding** so a request that lands on a standby Cluster forwards to the active one. This has two parts. From 1276f5e3a47d296c2add6ff2380d167a41af963d Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:38:16 -0700 Subject: [PATCH 09/54] Tighten failover behavior bullets Compress the 'What to expect on failover' list from five verbose bullets to four, folding the async-replication caveat into the permanent-loss point. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index e3891cc1cc..4391fb27ff 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -157,20 +157,13 @@ sequenceDiagram Note over C: caller Workflow completes ``` -- **Completion callbacks are delivered internally** to the caller Namespace's - current active Cluster, re-resolved on each attempt. There is no callback URL, - DNS, or routing layer to manage. -- **Forwarding runs on the surviving Cluster**, toward the active Cluster. It does - not depend on the failed Cluster, so planned failover and permanent Cluster loss - both work. -- **The caller and handler can be active on different Clusters.** The active - Cluster is set per Namespace, so the caller Namespace can be active on one Cluster - while the handler Namespace is active on another. The completion is then forwarded - across Clusters automatically, as long as each Cluster advertises its - `httpAddress` (requirement 3). -- **On permanent Cluster loss, fail over *every* Namespace off the lost Cluster** - (both caller and handler). A completion whose caller Namespace still points at the - lost Cluster retries until you do. -- **Caveat:** anything not replicated before a Cluster is lost is lost with it. - Long-running Operations replicate their setup state early, so a mid-flight - failover completes. +- **Callbacks are delivered internally** to the caller Namespace's active Cluster, + re-resolved on each attempt. No callback URL, DNS, or proxy to manage. +- **Forwarding runs on the surviving Cluster**, never the failed one, so planned + failover and permanent Cluster loss both work. +- **Caller and handler can be active on different Clusters** (active is per + Namespace). The completion forwards across Clusters automatically, as long as each + Cluster advertises its `httpAddress`. +- **On permanent Cluster loss, fail over every Namespace off it.** A completion + still pointing at the lost Cluster retries until you do; state not replicated + before the loss is lost with it. From 87d8e8e2811d23522e3e760ddfa529176fcb15d8 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:38:48 -0700 Subject: [PATCH 10/54] Shorten the httpAddress configuration step Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 4391fb27ff..a8e9f635b2 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -112,14 +112,12 @@ target an external URL (`--target-url`), which is experimental and not covered h [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. -3. **Advertise a frontend HTTP address on every Cluster.** [Enable Nexus](#enable-nexus) - sets `frontend.rpc.httpPort` and a `clusterInformation..httpAddress` for - one Cluster. For failover, set them on **every** Cluster, each with its own - address, so peers can reach it. Callback routing resolves this address at delivery - time. Without it, cross-Cluster callbacks fail with - `HTTPAddress not configured for cluster: `. The `operator cluster upsert` - command doesn't set `httpAddress`, so configure it explicitly and re-run `upsert` - after changing it. +3. **Advertise a frontend HTTP address on every Cluster.** Extend the `httpPort` + and `clusterInformation..httpAddress` from [Enable Nexus](#enable-nexus) + to **every** Cluster, each with its own address, so callback routing can resolve + it at delivery time. `operator cluster upsert` doesn't set `httpAddress`, so set + it explicitly; otherwise cross-Cluster callbacks fail with `HTTPAddress not + configured for cluster: `. 4. **Enable automatic forwarding** so a request that lands on a standby Cluster forwards to the active one. This has two parts. From 88f2f08e12b79009455ebba225ba268215a5645b Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:40:31 -0700 Subject: [PATCH 11/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index a8e9f635b2..a33ee4fc4c 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -108,17 +108,17 @@ target an external URL (`--target-url`), which is experimental and not covered h [Multi-Cluster Replication](/self-hosted-guide/multi-cluster-replication) for connecting Clusters and creating replicated Namespaces. -2. **Register Endpoints on every Cluster.** The - [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. - Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. - -3. **Advertise a frontend HTTP address on every Cluster.** Extend the `httpPort` +2. **Advertise a frontend HTTP address on every Cluster.** Extend the `httpPort` and `clusterInformation..httpAddress` from [Enable Nexus](#enable-nexus) to **every** Cluster, each with its own address, so callback routing can resolve it at delivery time. `operator cluster upsert` doesn't set `httpAddress`, so set it explicitly; otherwise cross-Cluster callbacks fail with `HTTPAddress not configured for cluster: `. +3. **Register Endpoints on every Cluster.** The + [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. + Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. + 4. **Enable automatic forwarding** so a request that lands on a standby Cluster forwards to the active one. This has two parts. From bd91b569184a592d7f61fbb183688b09d6762051 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:41:17 -0700 Subject: [PATCH 12/54] Drop operator cluster upsert caveat from httpAddress step It conflated the dynamic cluster-connection flow with the static-config instruction; httpAddress is set in static clusterInformation. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index a33ee4fc4c..eb406ee20a 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -111,9 +111,8 @@ target an external URL (`--target-url`), which is experimental and not covered h 2. **Advertise a frontend HTTP address on every Cluster.** Extend the `httpPort` and `clusterInformation..httpAddress` from [Enable Nexus](#enable-nexus) to **every** Cluster, each with its own address, so callback routing can resolve - it at delivery time. `operator cluster upsert` doesn't set `httpAddress`, so set - it explicitly; otherwise cross-Cluster callbacks fail with `HTTPAddress not - configured for cluster: `. + it at delivery time. Without it, cross-Cluster callbacks fail with `HTTPAddress + not configured for cluster: `. 3. **Register Endpoints on every Cluster.** The [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. From af98ee290b5ecaf3cc7e90a7d0dfb46e35091dd4 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:42:08 -0700 Subject: [PATCH 13/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index eb406ee20a..e053c1b0ca 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -110,33 +110,31 @@ target an external URL (`--target-url`), which is experimental and not covered h 2. **Advertise a frontend HTTP address on every Cluster.** Extend the `httpPort` and `clusterInformation..httpAddress` from [Enable Nexus](#enable-nexus) - to **every** Cluster, each with its own address, so callback routing can resolve - it at delivery time. Without it, cross-Cluster callbacks fail with `HTTPAddress - not configured for cluster: `. + to **every** Cluster, each with its own address. Without it, cross-Cluster + callbacks fail with `HTTPAddress not configured for cluster: `. 3. **Register Endpoints on every Cluster.** The [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. 4. **Enable automatic forwarding** so a request that lands on a standby Cluster - forwards to the active one. This has two parts. + forwards to the active one. Two parts: - Set the server's - [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) in static - config. It defaults to no redirection, so you must set it to - `all-apis-forwarding` (or `selected-apis-forwarding`): + - Set the server's [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) + in static config. It defaults to no redirection, so set it to + `all-apis-forwarding` (or `selected-apis-forwarding`): - ```yaml - dcRedirectionPolicy: - policy: "all-apis-forwarding" - ``` + ```yaml + dcRedirectionPolicy: + policy: "all-apis-forwarding" + ``` - Turn on auto-forwarding per Namespace in dynamic config: + - Turn on auto-forwarding per Namespace in dynamic config: - ```yaml - system.enableNamespaceNotActiveAutoForwarding: - - value: true - ``` + ```yaml + system.enableNamespaceNotActiveAutoForwarding: + - value: true + ``` ### What to expect on failover From 383a7a4e91464f76b3d11be6171395b29c7bb1a1 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:45:34 -0700 Subject: [PATCH 14/54] Elaborate auto-forwarding setting and fix failover diagram - Explain system.enableNamespaceNotActiveAutoForwarding (per-Namespace, defaults to true) and note it has the opposite default of dcRedirectionPolicy. - Redraw the failover sequence so replication (not a failover-time handoff) carries state to Cluster B; remove the misleading A->B arrow. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index e053c1b0ca..7155f7f896 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -118,7 +118,7 @@ target an external URL (`--target-url`), which is experimental and not covered h Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. 4. **Enable automatic forwarding** so a request that lands on a standby Cluster - forwards to the active one. Two parts: + forwards to the active one. - Set the server's [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) in static config. It defaults to no redirection, so set it to @@ -129,7 +129,11 @@ target an external URL (`--target-url`), which is experimental and not covered h policy: "all-apis-forwarding" ``` - - Turn on auto-forwarding per Namespace in dynamic config: + - `system.enableNamespaceNotActiveAutoForwarding` (dynamic, per-Namespace) + controls whether a Namespace that isn't active on the receiving Cluster + forwards its requests to its active Cluster. It defaults to `true`, so it's + usually already on — just confirm it hasn't been disabled for the caller + Namespace: ```yaml system.enableNamespaceNotActiveAutoForwarding: @@ -146,9 +150,10 @@ sequenceDiagram participant B as Cluster B C->>A: start async Nexus Operation A-->>C: Operation started, token returned - Note over A,B: Cluster A fails over or is lost, active moves to B - A->>B: handler Workflow and callback resume on B - B->>C: completion delivered to the caller's active Cluster + Note over A,B: Namespace state continuously replicates A → B + Note over A,B: failover: active moves to B (Cluster A may be lost) + Note over B: handler completes; callback fires from replicated state + B->>C: completion delivered on the caller's active Cluster Note over C: caller Workflow completes ``` From e90c423a5039a81cb1da9168d93b2ebc4b6896c3 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:47:20 -0700 Subject: [PATCH 15/54] Fix mermaid parse error and soften auto-forwarding wording - Remove semicolon from a sequence-diagram Note (mermaid treats ; as a statement separator, causing a render-time parse error). - Reword enableNamespaceNotActiveAutoForwarding as 'make sure it isn't turned off' since it defaults to true. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 7155f7f896..8ca8b487eb 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -129,16 +129,8 @@ target an external URL (`--target-url`), which is experimental and not covered h policy: "all-apis-forwarding" ``` - - `system.enableNamespaceNotActiveAutoForwarding` (dynamic, per-Namespace) - controls whether a Namespace that isn't active on the receiving Cluster - forwards its requests to its active Cluster. It defaults to `true`, so it's - usually already on — just confirm it hasn't been disabled for the caller - Namespace: - - ```yaml - system.enableNamespaceNotActiveAutoForwarding: - - value: true - ``` + - Make sure `system.enableNamespaceNotActiveAutoForwarding` isn't turned off for + the Namespace. This per-Namespace dynamic config defaults to `true`. ### What to expect on failover @@ -150,9 +142,7 @@ sequenceDiagram participant B as Cluster B C->>A: start async Nexus Operation A-->>C: Operation started, token returned - Note over A,B: Namespace state continuously replicates A → B - Note over A,B: failover: active moves to B (Cluster A may be lost) - Note over B: handler completes; callback fires from replicated state + Note over A,B: "Namespace state continuously replicates A → B" B->>C: completion delivered on the caller's active Cluster Note over C: caller Workflow completes ``` From 70e982cac74ea43a7ebc96e3d0be8288dff478c3 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:49:11 -0700 Subject: [PATCH 16/54] Fix cut-off note in failover diagram Drop the literal quotes and wrap the replication note across two lines so the Note-over box doesn't overflow. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 8ca8b487eb..e1d5b7cdda 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -142,7 +142,7 @@ sequenceDiagram participant B as Cluster B C->>A: start async Nexus Operation A-->>C: Operation started, token returned - Note over A,B: "Namespace state continuously replicates A → B" + Note over A,B: Namespace state continuously
replicates A → B B->>C: completion delivered on the caller's active Cluster Note over C: caller Workflow completes ``` From 030e6e3589178e288b9b8e3770f3011de27e0552 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:50:51 -0700 Subject: [PATCH 17/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index e1d5b7cdda..4dea1ce613 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -144,7 +144,7 @@ sequenceDiagram A-->>C: Operation started, token returned Note over A,B: Namespace state continuously
replicates A → B B->>C: completion delivered on the caller's active Cluster - Note over C: caller Workflow completes + Note over C: Nexus Operation completes ``` - **Callbacks are delivered internally** to the caller Namespace's active Cluster, From 628cb014138c00c81294e08bf81ec6a787bd6445 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:52:54 -0700 Subject: [PATCH 18/54] Replace failover sequence diagram with cluster/namespace topology Show both the caller and handler Namespaces replicated across both Clusters, active/standby per Namespace, and the cross-Cluster completion callback. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 4dea1ce613..64b72a710a 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -134,17 +134,26 @@ target an external URL (`--target-url`), which is experimental and not covered h ### What to expect on failover +Each Namespace is replicated across Clusters, and the active Cluster is set per +Namespace. When the caller and handler Namespaces are active on different Clusters, +the completion callback crosses Clusters: + ```mermaid -%%{init: {'sequence': {'mirrorActors': false}}}%% -sequenceDiagram - participant C as Caller Namespace - participant A as Cluster A - participant B as Cluster B - C->>A: start async Nexus Operation - A-->>C: Operation started, token returned - Note over A,B: Namespace state continuously
replicates A → B - B->>C: completion delivered on the caller's active Cluster - Note over C: Nexus Operation completes +flowchart LR + subgraph A["Cluster A"] + direction TB + caA["Caller Namespace
active"] + haA["Handler Namespace
standby"] + end + subgraph B["Cluster B"] + direction TB + caB["Caller Namespace
standby"] + haB["Handler Namespace
active"] + end + caA -. replicated .- caB + haA -. replicated .- haB + caA ==>|Nexus Operation| haB + haB ==>|completion callback| caA ``` - **Callbacks are delivered internally** to the caller Namespace's active Cluster, From 65a3a91aa8b650497097b86310ccbcb8eee5df94 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:56:05 -0700 Subject: [PATCH 19/54] Show before/after failover states in the diagram Use two cluster/namespace flowcharts: the Operation starting on the active Cluster, then the completion delivered on the new active Cluster after replication, so both the original and failover states are visible. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 64b72a710a..570ec11f2a 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -134,26 +134,38 @@ target an external URL (`--target-url`), which is experimental and not covered h ### What to expect on failover -Each Namespace is replicated across Clusters, and the active Cluster is set per -Namespace. When the caller and handler Namespaces are active on different Clusters, -the completion callback crosses Clusters: +Each Namespace is a Global Namespace replicated across both Clusters, with one +active Cluster per Namespace. An Operation started before a failover completes +after it, on the new active Cluster. + +**Before failover** — the Operation starts on the active Cluster: + +```mermaid +flowchart LR + subgraph A["Cluster A — active"] + caA["Caller Namespace"] -->|Nexus Operation| haA["Handler Namespace"] + end + subgraph B["Cluster B — standby"] + caB["Caller Namespace"] + haB["Handler Namespace"] + end + caA -. replicated .- caB + haA -. replicated .- haB +``` + +**After failover** — the completion is delivered on the new active Cluster: ```mermaid flowchart LR - subgraph A["Cluster A"] - direction TB - caA["Caller Namespace
active"] - haA["Handler Namespace
standby"] + subgraph A["Cluster A — lost or standby"] + caA["Caller Namespace"] + haA["Handler Namespace"] end - subgraph B["Cluster B"] - direction TB - caB["Caller Namespace
standby"] - haB["Handler Namespace
active"] + subgraph B["Cluster B — now active"] + haB["Handler Namespace"] -->|completion callback| caB["Caller Namespace"] end caA -. replicated .- caB haA -. replicated .- haB - caA ==>|Nexus Operation| haB - haB ==>|completion callback| caA ``` - **Callbacks are delivered internally** to the caller Namespace's active Cluster, From 0853333ca880dc1ee6847bdfe43edd96720a6b71 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:57:49 -0700 Subject: [PATCH 20/54] Use a sequence diagram with Cluster boxes for failover Group the caller and handler Namespaces into Cluster A and Cluster B boxes, and show the Operation starting while Cluster A is active, replication, failover, and completion once Cluster B is active. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 42 +++++++------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 570ec11f2a..78366e6931 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -136,36 +136,26 @@ target an external URL (`--target-url`), which is experimental and not covered h Each Namespace is a Global Namespace replicated across both Clusters, with one active Cluster per Namespace. An Operation started before a failover completes -after it, on the new active Cluster. - -**Before failover** — the Operation starts on the active Cluster: - -```mermaid -flowchart LR - subgraph A["Cluster A — active"] - caA["Caller Namespace"] -->|Nexus Operation| haA["Handler Namespace"] - end - subgraph B["Cluster B — standby"] - caB["Caller Namespace"] - haB["Handler Namespace"] - end - caA -. replicated .- caB - haA -. replicated .- haB -``` - -**After failover** — the completion is delivered on the new active Cluster: +after it, on the new active Cluster: ```mermaid -flowchart LR - subgraph A["Cluster A — lost or standby"] - caA["Caller Namespace"] - haA["Handler Namespace"] +sequenceDiagram + box Cluster A + participant caA as Caller ns + participant haA as Handler ns end - subgraph B["Cluster B — now active"] - haB["Handler Namespace"] -->|completion callback| caB["Caller Namespace"] + box Cluster B + participant caB as Caller ns + participant haB as Handler ns end - caA -. replicated .- caB - haA -. replicated .- haB + Note over caA,haA: Cluster A active + caA->>haA: start Nexus Operation + haA-->>caA: Operation started, token returned + Note over caA,haB: Namespace state replicates A to B + Note over caA,haB: failover, active moves to Cluster B + Note over caB,haB: Cluster B active + haB->>caB: completion delivered (callback) + Note over caB: Caller Workflow completes ``` - **Callbacks are delivered internally** to the caller Namespace's active Cluster, From c76f7ea56463d5c46d392dfbedb10ccb2cb75904 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 11:58:41 -0700 Subject: [PATCH 21/54] Add boom emoji to the failover note in the diagram Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 78366e6931..b532fe741f 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -152,7 +152,7 @@ sequenceDiagram caA->>haA: start Nexus Operation haA-->>caA: Operation started, token returned Note over caA,haB: Namespace state replicates A to B - Note over caA,haB: failover, active moves to Cluster B + Note over caA,haB: 💥 failover, active moves to Cluster B Note over caB,haB: Cluster B active haB->>caB: completion delivered (callback) Note over caB: Caller Workflow completes From 92a7ad78b03d1e1f683914204d98fa48b6826632 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:01:35 -0700 Subject: [PATCH 22/54] Use full 'Namespace', HTML bold for active-Cluster notes, rename final note - Expand 'ns' to 'Namespace' in the sequence diagram participants. - Bold the active-Cluster notes with (markdown strings rendered literally). - Rename the final note to 'Nexus Operation completes'. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index b532fe741f..23893ed5b9 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -141,21 +141,21 @@ after it, on the new active Cluster: ```mermaid sequenceDiagram box Cluster A - participant caA as Caller ns - participant haA as Handler ns + participant caA as Caller Namespace + participant haA as Handler Namespace end box Cluster B - participant caB as Caller ns - participant haB as Handler ns + participant caB as Caller Namespace + participant haB as Handler Namespace end - Note over caA,haA: Cluster A active + Note over caA,haA: Cluster A active caA->>haA: start Nexus Operation haA-->>caA: Operation started, token returned Note over caA,haB: Namespace state replicates A to B Note over caA,haB: 💥 failover, active moves to Cluster B - Note over caB,haB: Cluster B active + Note over caB,haB: Cluster B active haB->>caB: completion delivered (callback) - Note over caB: Caller Workflow completes + Note over caB: Nexus Operation completes ``` - **Callbacks are delivered internally** to the caller Namespace's active Cluster, From 63eed47591989eb848670327a214572a6a705b6f Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:05:38 -0700 Subject: [PATCH 23/54] Revert HTML bold in diagram notes (not rendered under strict mermaid) Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 23893ed5b9..0f73f47434 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -148,12 +148,12 @@ sequenceDiagram participant caB as Caller Namespace participant haB as Handler Namespace end - Note over caA,haA: Cluster A active + Note over caA,haA: Cluster A active caA->>haA: start Nexus Operation haA-->>caA: Operation started, token returned Note over caA,haB: Namespace state replicates A to B Note over caA,haB: 💥 failover, active moves to Cluster B - Note over caB,haB: Cluster B active + Note over caB,haB: Cluster B active haB->>caB: completion delivered (callback) Note over caB: Nexus Operation completes ``` From 29d8dc01b2ea19f53527bd9c4c7f07e9f2951741 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:11:04 -0700 Subject: [PATCH 24/54] Shorten failover behavior bullets Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 0f73f47434..45003b5d14 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -158,13 +158,11 @@ sequenceDiagram Note over caB: Nexus Operation completes ``` -- **Callbacks are delivered internally** to the caller Namespace's active Cluster, - re-resolved on each attempt. No callback URL, DNS, or proxy to manage. -- **Forwarding runs on the surviving Cluster**, never the failed one, so planned - failover and permanent Cluster loss both work. -- **Caller and handler can be active on different Clusters** (active is per - Namespace). The completion forwards across Clusters automatically, as long as each - Cluster advertises its `httpAddress`. -- **On permanent Cluster loss, fail over every Namespace off it.** A completion - still pointing at the lost Cluster retries until you do; state not replicated - before the loss is lost with it. +- **Callbacks are delivered internally** to the caller's active Cluster, re-resolved + on each attempt. No callback URL, DNS, or proxy needed. +- **Forwarding runs on a surviving Cluster**, never the failed one, so planned + failover and permanent loss both work. +- **Caller and handler can be active on different Clusters.** Cross-Cluster + completions forward automatically when every Cluster advertises its `httpAddress`. +- **On permanent Cluster loss, fail over every Namespace off it.** Completions to the + lost Cluster retry until you do, and unreplicated state is lost. From 4ae511267b38c144508eaa344fe8f3865bbda601 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:15:21 -0700 Subject: [PATCH 25/54] Make failover bullets value-first Lead each with the operator takeaway: no external callback infrastructure, survives permanent region loss, why cross-Cluster completions need httpAddress, and the permanent-loss action plus caveat. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 45003b5d14..b80c4d057a 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -158,11 +158,12 @@ sequenceDiagram Note over caB: Nexus Operation completes ``` -- **Callbacks are delivered internally** to the caller's active Cluster, re-resolved - on each attempt. No callback URL, DNS, or proxy needed. -- **Forwarding runs on a surviving Cluster**, never the failed one, so planned - failover and permanent loss both work. -- **Caller and handler can be active on different Clusters.** Cross-Cluster - completions forward automatically when every Cluster advertises its `httpAddress`. -- **On permanent Cluster loss, fail over every Namespace off it.** Completions to the - lost Cluster retry until you do, and unreplicated state is lost. +- **No external callback infrastructure.** Worker-target completions route + internally, so there's no callback URL, DNS, or proxy to manage. +- **Survives permanent region loss, not just planned failover.** A surviving Cluster + delivers the completion. +- **Caller and handler can be active on different Clusters** (active is per + Namespace), so a completion can cross Clusters. This is why every Cluster must + advertise its `httpAddress`. +- **On permanent loss, fail over every Namespace off the dead Cluster.** Unreplicated + state is lost. From 0ee80787e9bc9a3aff1d3b28689068190d40c33b Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:16:59 -0700 Subject: [PATCH 26/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index b80c4d057a..f752fc54f8 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -158,12 +158,8 @@ sequenceDiagram Note over caB: Nexus Operation completes ``` -- **No external callback infrastructure.** Worker-target completions route - internally, so there's no callback URL, DNS, or proxy to manage. - **Survives permanent region loss, not just planned failover.** A surviving Cluster delivers the completion. - **Caller and handler can be active on different Clusters** (active is per Namespace), so a completion can cross Clusters. This is why every Cluster must advertise its `httpAddress`. -- **On permanent loss, fail over every Namespace off the dead Cluster.** Unreplicated - state is lost. From ff8096b404679303af1562990d87d4f40b9d95e0 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:23:33 -0700 Subject: [PATCH 27/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index f752fc54f8..8df9a16080 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -134,9 +134,7 @@ target an external URL (`--target-url`), which is experimental and not covered h ### What to expect on failover -Each Namespace is a Global Namespace replicated across both Clusters, with one -active Cluster per Namespace. An Operation started before a failover completes -after it, on the new active Cluster: +A Nexus Operation started before a cluster failover completes on the new active Cluster: ```mermaid sequenceDiagram @@ -151,15 +149,10 @@ sequenceDiagram Note over caA,haA: Cluster A active caA->>haA: start Nexus Operation haA-->>caA: Operation started, token returned - Note over caA,haB: Namespace state replicates A to B - Note over caA,haB: 💥 failover, active moves to Cluster B + Note over caA,haB: 💥 Failover from Cluster A to B Note over caB,haB: Cluster B active haB->>caB: completion delivered (callback) Note over caB: Nexus Operation completes ``` -- **Survives permanent region loss, not just planned failover.** A surviving Cluster - delivers the completion. -- **Caller and handler can be active on different Clusters** (active is per - Namespace), so a completion can cross Clusters. This is why every Cluster must - advertise its `httpAddress`. +Callbacks are delivered to the caller namespace's active Cluster, re-resolved on each attempt. From 49cade2d360e39a55f7b7431e43da639845a4a7d Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:25:51 -0700 Subject: [PATCH 28/54] Restore async-replication caveat and fix proper-noun casing Add the abrupt-region-loss caveat (fail over every Namespace; unreplicated state is lost) and capitalize Cluster/Namespace. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 8df9a16080..996bf486e2 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -134,7 +134,7 @@ target an external URL (`--target-url`), which is experimental and not covered h ### What to expect on failover -A Nexus Operation started before a cluster failover completes on the new active Cluster: +A Nexus Operation started before a Cluster failover completes on the new active Cluster: ```mermaid sequenceDiagram @@ -155,4 +155,6 @@ sequenceDiagram Note over caB: Nexus Operation completes ``` -Callbacks are delivered to the caller namespace's active Cluster, re-resolved on each attempt. +Callbacks are delivered to the caller Namespace's active Cluster, re-resolved on each attempt. + +On an abrupt region loss, fail over every Namespace off the lost Cluster. Replication is asynchronous, so state not replicated before the loss is lost. From 75fe1a4a8349e1582f8fb456a024201842223475 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:27:04 -0700 Subject: [PATCH 29/54] Reframe abrupt-loss note as a warning admonition Describe the risks (unreplicated state lost, Namespace stuck until failover) instead of giving an instruction. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 996bf486e2..cacd57b93a 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -157,4 +157,10 @@ sequenceDiagram Callbacks are delivered to the caller Namespace's active Cluster, re-resolved on each attempt. -On an abrupt region loss, fail over every Namespace off the lost Cluster. Replication is asynchronous, so state not replicated before the loss is lost. +:::warning Abrupt region loss + +Replication is asynchronous, so any state not replicated before the loss is lost. +A Namespace still active on the lost Cluster stays stuck until it's failed over to +a surviving Cluster. + +::: From 41f7c06159bb57e3178da145df33c84d9a47895d Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:45:09 -0700 Subject: [PATCH 30/54] Soften abrupt-loss note (warning to note, neutral wording) Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index cacd57b93a..de05435575 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -157,10 +157,10 @@ sequenceDiagram Callbacks are delivered to the caller Namespace's active Cluster, re-resolved on each attempt. -:::warning Abrupt region loss +:::note Abrupt region loss -Replication is asynchronous, so any state not replicated before the loss is lost. -A Namespace still active on the lost Cluster stays stuck until it's failed over to -a surviving Cluster. +Replication is asynchronous, so state not replicated before the loss is lost. A +Namespace still active on the lost Cluster resumes once it's failed over to a +surviving Cluster. ::: From 01a3064e76d6e04583b0c0a6d6524f44f5c9477c Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:45:41 -0700 Subject: [PATCH 31/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index de05435575..deae873e69 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -156,11 +156,3 @@ sequenceDiagram ``` Callbacks are delivered to the caller Namespace's active Cluster, re-resolved on each attempt. - -:::note Abrupt region loss - -Replication is asynchronous, so state not replicated before the loss is lost. A -Namespace still active on the lost Cluster resumes once it's failed over to a -surviving Cluster. - -::: From 9b622208dc243a8b3eda0fd65f5d4039c2f7bb6c Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:47:00 -0700 Subject: [PATCH 32/54] Fold callback-delivery detail into the failover lead-in Move the orphaned trailing sentence into the paragraph before the diagram. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index deae873e69..dc219bb6c9 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -134,7 +134,9 @@ target an external URL (`--target-url`), which is experimental and not covered h ### What to expect on failover -A Nexus Operation started before a Cluster failover completes on the new active Cluster: +A Nexus Operation started before a Cluster failover completes on the new active +Cluster. The completion callback is delivered to the caller Namespace's current +active Cluster, re-resolved on each attempt: ```mermaid sequenceDiagram @@ -154,5 +156,3 @@ sequenceDiagram haB->>caB: completion delivered (callback) Note over caB: Nexus Operation completes ``` - -Callbacks are delivered to the caller Namespace's active Cluster, re-resolved on each attempt. From 1dee3a4794aed4f67ef0371837ce4472b8280857 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:51:27 -0700 Subject: [PATCH 33/54] Show a failed callback attempt and retry in the diagram Co-Authored-By: Claude Opus 4.8 (1M context) --- .../production-deployment/self-hosted-guide/temporal-nexus.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index dc219bb6c9..3ae43ce8e3 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -153,6 +153,7 @@ sequenceDiagram haA-->>caA: Operation started, token returned Note over caA,haB: 💥 Failover from Cluster A to B Note over caB,haB: Cluster B active - haB->>caB: completion delivered (callback) + haB-xcaB: completion attempt fails (retryable) + haB->>caB: retry delivers the completion Note over caB: Nexus Operation completes ``` From 29c41c3bdbac660dad8cf479631fdcff1dbc893a Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:54:22 -0700 Subject: [PATCH 34/54] Clarify forwarding: Nexus vs client-API paths; drop selected-apis-forwarding - enableNamespaceNotActiveAutoForwarding gates Nexus request/callback forwarding. - dcRedirectionPolicy forwards Workflow/Activity client APIs (not Nexus). - Recommend only all-apis-forwarding; drop the selected-apis-forwarding aside, which doesn't cover Nexus and is an unnecessary footgun here. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 3ae43ce8e3..f8c9baef5a 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -117,21 +117,22 @@ target an external URL (`--target-url`), which is experimental and not covered h [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. -4. **Enable automatic forwarding** so a request that lands on a standby Cluster - forwards to the active one. +4. **Enable cross-Cluster forwarding.** Two independent settings apply: - - Set the server's [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) - in static config. It defaults to no redirection, so set it to - `all-apis-forwarding` (or `selected-apis-forwarding`): + - **Nexus requests and callbacks** are forwarded by + `system.enableNamespaceNotActiveAutoForwarding` (per-Namespace dynamic config, + defaults to `true`). Make sure it isn't turned off for the Namespace. + + - **Workflow and Activity client APIs** (so callers and clients reach the active + Cluster from either side) are forwarded by the server's + [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) in static + config. It defaults to no redirection, so set it to `all-apis-forwarding`: ```yaml dcRedirectionPolicy: policy: "all-apis-forwarding" ``` - - Make sure `system.enableNamespaceNotActiveAutoForwarding` isn't turned off for - the Namespace. This per-Namespace dynamic config defaults to `true`. - ### What to expect on failover A Nexus Operation started before a Cluster failover completes on the new active From b2e663de143069272f4f60a41dc462b671757ca1 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:55:18 -0700 Subject: [PATCH 35/54] Update temporal-nexus.mdx --- .../production-deployment/self-hosted-guide/temporal-nexus.mdx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index f8c9baef5a..c9e1fd7433 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -110,8 +110,7 @@ target an external URL (`--target-url`), which is experimental and not covered h 2. **Advertise a frontend HTTP address on every Cluster.** Extend the `httpPort` and `clusterInformation..httpAddress` from [Enable Nexus](#enable-nexus) - to **every** Cluster, each with its own address. Without it, cross-Cluster - callbacks fail with `HTTPAddress not configured for cluster: `. + to **every** Cluster, each with its own address. 3. **Register Endpoints on every Cluster.** The [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. From e42e4f96300e44fdfa3d0f3f18fae93b7406c056 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:57:49 -0700 Subject: [PATCH 36/54] Demote dcRedirectionPolicy to optional in forwarding step Nexus forwarding is on by default (enableNamespaceNotActiveAutoForwarding). dcRedirectionPolicy is an optional client-API convenience, not a requirement (default noop; not mandated by the multi-cluster docs). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index c9e1fd7433..771888e884 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -116,21 +116,12 @@ target an external URL (`--target-url`), which is experimental and not covered h [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. -4. **Enable cross-Cluster forwarding.** Two independent settings apply: - - - **Nexus requests and callbacks** are forwarded by - `system.enableNamespaceNotActiveAutoForwarding` (per-Namespace dynamic config, - defaults to `true`). Make sure it isn't turned off for the Namespace. - - - **Workflow and Activity client APIs** (so callers and clients reach the active - Cluster from either side) are forwarded by the server's - [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) in static - config. It defaults to no redirection, so set it to `all-apis-forwarding`: - - ```yaml - dcRedirectionPolicy: - policy: "all-apis-forwarding" - ``` +4. **Cross-Cluster forwarding.** Nexus request and callback forwarding is on by + default via `system.enableNamespaceNotActiveAutoForwarding` (per-Namespace + dynamic config); just don't disable it. Optionally, set the server's + [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) to + `all-apis-forwarding` so Workflow and Activity client APIs also forward to the + active Cluster when a client connects to a standby. ### What to expect on failover From 3c2a9dc3f1fe679663910d5f6821a573ef6d03b0 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:58:20 -0700 Subject: [PATCH 37/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 771888e884..8758e5b1ac 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -118,10 +118,10 @@ target an external URL (`--target-url`), which is experimental and not covered h 4. **Cross-Cluster forwarding.** Nexus request and callback forwarding is on by default via `system.enableNamespaceNotActiveAutoForwarding` (per-Namespace - dynamic config); just don't disable it. Optionally, set the server's + dynamic config). Optionally, set the server's [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) to - `all-apis-forwarding` so Workflow and Activity client APIs also forward to the - active Cluster when a client connects to a standby. + `all-apis-forwarding` so client requests also forward to the + active Cluster when it connects to a standby. ### What to expect on failover From 7dd709840f5fa38691eefc5debe15ffa65a8bde9 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:58:53 -0700 Subject: [PATCH 38/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 8758e5b1ac..8cbbf0d8b8 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -144,7 +144,6 @@ sequenceDiagram haA-->>caA: Operation started, token returned Note over caA,haB: 💥 Failover from Cluster A to B Note over caB,haB: Cluster B active - haB-xcaB: completion attempt fails (retryable) haB->>caB: retry delivers the completion Note over caB: Nexus Operation completes ``` From 62a080e0af5b80e03f06f649e640ca0168d91f4f Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 12:59:07 -0700 Subject: [PATCH 39/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 8cbbf0d8b8..6d633ac677 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -144,6 +144,6 @@ sequenceDiagram haA-->>caA: Operation started, token returned Note over caA,haB: 💥 Failover from Cluster A to B Note over caB,haB: Cluster B active - haB->>caB: retry delivers the completion + haB->>caB: deliver completion callback Note over caB: Nexus Operation completes ``` From b40a311e690efa46876b144737c60e32a3575a94 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:00:31 -0700 Subject: [PATCH 40/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 6d633ac677..a0cdf5d0bc 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -142,8 +142,8 @@ sequenceDiagram Note over caA,haA: Cluster A active caA->>haA: start Nexus Operation haA-->>caA: Operation started, token returned - Note over caA,haB: 💥 Failover from Cluster A to B + Note over caA,haB: 💥 Failover both namespaces from Cluster A to B Note over caB,haB: Cluster B active - haB->>caB: deliver completion callback + haB->>caB: deliver completion callback Note over caB: Nexus Operation completes ``` From 3d71d3ef2c3e0891f8531c7150fbc0b917c22806 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:01:22 -0700 Subject: [PATCH 41/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index a0cdf5d0bc..0aabd57d1c 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -2,7 +2,7 @@ id: nexus title: Self-hosted Temporal Nexus sidebar_label: Temporal Nexus -description: Use Nexus in your self-hosted Temporal Service, including across Global (multi-region) Namespaces and failover. +description: Use Nexus in your self-hosted Temporal Service, including across Global (multi-region) Namespaces. toc_max_heading_level: 4 keywords: - self-hosted From 9d37e2f6c7fe71a5bb752e12871a46234ee54ba2 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:02:02 -0700 Subject: [PATCH 42/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 0aabd57d1c..6f4466f19d 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -142,7 +142,7 @@ sequenceDiagram Note over caA,haA: Cluster A active caA->>haA: start Nexus Operation haA-->>caA: Operation started, token returned - Note over caA,haB: 💥 Failover both namespaces from Cluster A to B + Note over caA,haB: 💥 Fail over both namespaces from Cluster A to B Note over caB,haB: Cluster B active haB->>caB: deliver completion callback Note over caB: Nexus Operation completes From 7f04fe616e9d3467987fbd8c135ce73b307a0291 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:03:11 -0700 Subject: [PATCH 43/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 6f4466f19d..bb25c3940e 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -125,8 +125,8 @@ target an external URL (`--target-url`), which is experimental and not covered h ### What to expect on failover -A Nexus Operation started before a Cluster failover completes on the new active -Cluster. The completion callback is delivered to the caller Namespace's current +For a Nexus Operation started before a Cluster failover completes on the new active +Cluster, the completion callback is delivered to the caller Namespace's current active Cluster, re-resolved on each attempt: ```mermaid From 4f8ffe6dd23f4169e45d0514734a64cb9a39e82f Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:19:30 -0700 Subject: [PATCH 44/54] Use a flowchart with Cluster subgraphs for the failover diagram The CI mermaid linter parses headless (no DOM) and can't handle sequence 'box'. A flowchart with subgraphs shows the same Cluster boxes containing the Namespaces and passes the linter. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index bb25c3940e..ca49b3ee85 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -130,20 +130,17 @@ Cluster, the completion callback is delivered to the caller Namespace's current active Cluster, re-resolved on each attempt: ```mermaid -sequenceDiagram - box Cluster A - participant caA as Caller Namespace - participant haA as Handler Namespace +flowchart LR + subgraph A["Cluster A (initially active)"] + caA["Caller Namespace"] + haA["Handler Namespace"] end - box Cluster B - participant caB as Caller Namespace - participant haB as Handler Namespace + subgraph B["Cluster B (active after failover)"] + caB["Caller Namespace"] + haB["Handler Namespace"] end - Note over caA,haA: Cluster A active - caA->>haA: start Nexus Operation - haA-->>caA: Operation started, token returned - Note over caA,haB: 💥 Fail over both namespaces from Cluster A to B - Note over caB,haB: Cluster B active - haB->>caB: deliver completion callback - Note over caB: Nexus Operation completes + caA -->|"1 start Nexus Operation"| haA + caA -. replicated .- caB + haA -. replicated .- haB + haB -->|"2 completion callback, after failover"| caB ``` From 92b3a5238126bfc288a2336ed99bfafd4e4434dd Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:26:44 -0700 Subject: [PATCH 45/54] Give the mermaid linter a DOM so it can parse sequence box lint-mermaid runs mermaid.parse() headless, which fails on syntaxes that need browser DOM APIs (e.g. sequence-diagram 'box': 'window is not defined'). Set up a jsdom DOM before loading mermaid, and add jsdom as a devDependency (it was only a transitive dep before). Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 3 ++- scripts/lint-mermaid.mjs | 36 +++++++++++++++++++----------------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 2751d77a28..342a1e3727 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "eslint": "^9.8.0", "eslint-plugin-react": "^7.23.2", "husky": "^9.1.7", - "hyperlink": "^5.0.4" + "hyperlink": "^5.0.4", + "jsdom": "^19.0.0" } } diff --git a/scripts/lint-mermaid.mjs b/scripts/lint-mermaid.mjs index 0e68d39b9d..466a478860 100644 --- a/scripts/lint-mermaid.mjs +++ b/scripts/lint-mermaid.mjs @@ -1,9 +1,25 @@ import fs from 'node:fs/promises'; import path from 'node:path'; -import DOMPurify from 'dompurify'; -import mermaidModule from 'mermaid'; +import { JSDOM } from 'jsdom'; + +// Mermaid parses using browser DOM APIs; some diagram syntaxes (for example a +// sequence diagram `box`) reference window/document/Option during parse and +// fail headless with "window is not defined". Provide a DOM before loading +// mermaid so `mermaid.parse` works in CI. +const dom = new JSDOM(''); +globalThis.window = dom.window; +globalThis.document = dom.window.document; +for (const key of Object.getOwnPropertyNames(dom.window)) { + if (!(key in globalThis)) { + try { + globalThis[key] = dom.window[key]; + } catch { + // Some window properties are getters that throw when read standalone. + } + } +} -const mermaid = mermaidModule.default ?? mermaidModule; +const { default: mermaid } = await import('mermaid'); const DOCS_ROOT = path.resolve('docs'); const MARKDOWN_EXTENSIONS = new Set(['.md', '.mdx']); @@ -109,20 +125,6 @@ async function lintFile(filePath) { } async function main() { - // Mermaid's parser may call DOMPurify hooks for some diagram syntaxes. - // In Node (without a browser window), dompurify can resolve to a minimal - // implementation that lacks hook APIs; provide no-op hooks so syntax-only - // parsing still works in CI. - if (typeof DOMPurify.addHook !== 'function') { - DOMPurify.addHook = () => {}; - } - if (typeof DOMPurify.removeHook !== 'function') { - DOMPurify.removeHook = () => {}; - } - if (typeof DOMPurify.sanitize !== 'function') { - DOMPurify.sanitize = (value) => value; - } - mermaid.initialize({ startOnLoad: false }); const markdownFiles = await walk(DOCS_ROOT); From d2e20f4023010b4487edf8c2e939e63a13b8d7d9 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:26:45 -0700 Subject: [PATCH 46/54] Restore sequence box failover diagram; note selected-apis-forwarding - Use the sequence diagram with Cluster boxes (now that the linter parses it). - dcRedirectionPolicy: mention selected-apis-forwarding forwards StartNexusOperationExecution for standalone Nexus Operations. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index ca49b3ee85..b9fa13fd18 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -119,9 +119,11 @@ target an external URL (`--target-url`), which is experimental and not covered h 4. **Cross-Cluster forwarding.** Nexus request and callback forwarding is on by default via `system.enableNamespaceNotActiveAutoForwarding` (per-Namespace dynamic config). Optionally, set the server's - [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) to - `all-apis-forwarding` so client requests also forward to the - active Cluster when it connects to a standby. + [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) so client + requests forward to the active Cluster when a client connects to a standby: use + `all-apis-forwarding` for all client APIs, or `selected-apis-forwarding` for a + fixed subset that includes `StartNexusOperationExecution` (used to start a + standalone Nexus Operation). ### What to expect on failover @@ -130,17 +132,20 @@ Cluster, the completion callback is delivered to the caller Namespace's current active Cluster, re-resolved on each attempt: ```mermaid -flowchart LR - subgraph A["Cluster A (initially active)"] - caA["Caller Namespace"] - haA["Handler Namespace"] +sequenceDiagram + box Cluster A + participant caA as Caller Namespace + participant haA as Handler Namespace end - subgraph B["Cluster B (active after failover)"] - caB["Caller Namespace"] - haB["Handler Namespace"] + box Cluster B + participant caB as Caller Namespace + participant haB as Handler Namespace end - caA -->|"1 start Nexus Operation"| haA - caA -. replicated .- caB - haA -. replicated .- haB - haB -->|"2 completion callback, after failover"| caB + Note over caA,haA: Cluster A active + caA->>haA: start Nexus Operation + haA-->>caA: Operation started, token returned + Note over caA,haB: 💥 Fail over both namespaces from Cluster A to B + Note over caB,haB: Cluster B active + haB->>caB: deliver completion callback + Note over caB: Nexus Operation completes ``` From f7576ed6d322a524bd27a4e17191e7b60d75f215 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:30:00 -0700 Subject: [PATCH 47/54] Update temporal-nexus.mdx --- .../self-hosted-guide/temporal-nexus.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index b9fa13fd18..911507b76b 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -118,7 +118,9 @@ target an external URL (`--target-url`), which is experimental and not covered h 4. **Cross-Cluster forwarding.** Nexus request and callback forwarding is on by default via `system.enableNamespaceNotActiveAutoForwarding` (per-Namespace - dynamic config). Optionally, set the server's + dynamic config). + + Optionally, set the server's [`dcRedirectionPolicy`](/references/configuration#dcredirectionpolicy) so client requests forward to the active Cluster when a client connects to a standby: use `all-apis-forwarding` for all client APIs, or `selected-apis-forwarding` for a From 668317ecb9ec2ede82f55015db7f8900846faf45 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:30:15 -0700 Subject: [PATCH 48/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 911507b76b..69a6786d4b 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -125,7 +125,7 @@ target an external URL (`--target-url`), which is experimental and not covered h requests forward to the active Cluster when a client connects to a standby: use `all-apis-forwarding` for all client APIs, or `selected-apis-forwarding` for a fixed subset that includes `StartNexusOperationExecution` (used to start a - standalone Nexus Operation). + [standalone Nexus Operation](/standalone-nexus-operation)). ### What to expect on failover From 80a3e420592b5e18ebcbc38bd9751bb757e804d4 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:32:50 -0700 Subject: [PATCH 49/54] Use global-jsdom for the mermaid linter DOM setup Replace the manual jsdom global-copy loop with a one-line 'import global-jsdom/register'. (jsdom-global is unmaintained and doesn't expose the globals mermaid's box syntax needs; global-jsdom does.) Swap the direct jsdom devDependency for global-jsdom. Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 4 ++-- scripts/lint-mermaid.mjs | 26 ++++++-------------------- yarn.lock | 5 +++++ 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 342a1e3727..d39a0e2da8 100644 --- a/package.json +++ b/package.json @@ -105,8 +105,8 @@ "dprint": "^0.55.1", "eslint": "^9.8.0", "eslint-plugin-react": "^7.23.2", + "global-jsdom": "^29.0.0", "husky": "^9.1.7", - "hyperlink": "^5.0.4", - "jsdom": "^19.0.0" + "hyperlink": "^5.0.4" } } diff --git a/scripts/lint-mermaid.mjs b/scripts/lint-mermaid.mjs index 466a478860..cbb487a511 100644 --- a/scripts/lint-mermaid.mjs +++ b/scripts/lint-mermaid.mjs @@ -1,25 +1,11 @@ +// Set up a browser-like DOM before loading mermaid. mermaid.parse() uses DOM +// APIs for some diagram syntaxes (for example a sequence diagram `box`) and +// otherwise fails headless with "window is not defined". +import 'global-jsdom/register'; + import fs from 'node:fs/promises'; import path from 'node:path'; -import { JSDOM } from 'jsdom'; - -// Mermaid parses using browser DOM APIs; some diagram syntaxes (for example a -// sequence diagram `box`) reference window/document/Option during parse and -// fail headless with "window is not defined". Provide a DOM before loading -// mermaid so `mermaid.parse` works in CI. -const dom = new JSDOM(''); -globalThis.window = dom.window; -globalThis.document = dom.window.document; -for (const key of Object.getOwnPropertyNames(dom.window)) { - if (!(key in globalThis)) { - try { - globalThis[key] = dom.window[key]; - } catch { - // Some window properties are getters that throw when read standalone. - } - } -} - -const { default: mermaid } = await import('mermaid'); +import mermaid from 'mermaid'; const DOCS_ROOT = path.resolve('docs'); const MARKDOWN_EXTENSIONS = new Set(['.md', '.mdx']); diff --git a/yarn.lock b/yarn.lock index 005f797302..83c7848833 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8098,6 +8098,11 @@ global-dirs@^3.0.0: dependencies: ini "2.0.0" +global-jsdom@^29.0.0: + version "29.0.0" + resolved "https://registry.yarnpkg.com/global-jsdom/-/global-jsdom-29.0.0.tgz#c7c7f51d58f8069d94563afb5d7b8cd34546d64e" + integrity sha512-S9Wl+EHDfkO8DYleqMYzf14hKfwIysEN/FvoVRdPif3uUGUlmiHs/gj1PVKXhmJ20DwUVACtdxxhNYYvvn9K7A== + globals@^14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" From 05e3d32e90186ea1f335d1fbdcc2bd18f4a2cdd5 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:34:58 -0700 Subject: [PATCH 50/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 69a6786d4b..1347868a5c 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -125,7 +125,7 @@ target an external URL (`--target-url`), which is experimental and not covered h requests forward to the active Cluster when a client connects to a standby: use `all-apis-forwarding` for all client APIs, or `selected-apis-forwarding` for a fixed subset that includes `StartNexusOperationExecution` (used to start a - [standalone Nexus Operation](/standalone-nexus-operation)). + [Standalone Nexus Operation](/standalone-nexus-operation)). ### What to expect on failover From ff720fd2a1a7a782c9e5dca2a08d8fdfb770900f Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:36:34 -0700 Subject: [PATCH 51/54] Clarify the advertise-httpAddress step Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 1347868a5c..af31fc4900 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -108,9 +108,10 @@ target an external URL (`--target-url`), which is experimental and not covered h [Multi-Cluster Replication](/self-hosted-guide/multi-cluster-replication) for connecting Clusters and creating replicated Namespaces. -2. **Advertise a frontend HTTP address on every Cluster.** Extend the `httpPort` - and `clusterInformation..httpAddress` from [Enable Nexus](#enable-nexus) - to **every** Cluster, each with its own address. +2. **Advertise a frontend HTTP address on every Cluster.** [Enable Nexus](#enable-nexus) + sets `frontend.rpc.httpPort` and `clusterInformation..httpAddress` for + one Cluster. Set both on **every** Cluster, each with its own address, so the + other Clusters can reach it to deliver callbacks. 3. **Register Endpoints on every Cluster.** The [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. From 6ee1921196149a8af267ee5501ad115bb5198a5a Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:37:37 -0700 Subject: [PATCH 52/54] Reword step 2 so the reader is the actor, not the section Co-Authored-By: Claude Opus 4.8 (1M context) --- .../self-hosted-guide/temporal-nexus.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index af31fc4900..76d8ee5c6b 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -108,10 +108,10 @@ target an external URL (`--target-url`), which is experimental and not covered h [Multi-Cluster Replication](/self-hosted-guide/multi-cluster-replication) for connecting Clusters and creating replicated Namespaces. -2. **Advertise a frontend HTTP address on every Cluster.** [Enable Nexus](#enable-nexus) - sets `frontend.rpc.httpPort` and `clusterInformation..httpAddress` for - one Cluster. Set both on **every** Cluster, each with its own address, so the - other Clusters can reach it to deliver callbacks. +2. **Advertise a frontend HTTP address on every Cluster.** Set + `frontend.rpc.httpPort` and `clusterInformation..httpAddress` (shown in + [Enable Nexus](#enable-nexus) for one Cluster) on **every** Cluster, each with its + own address, so the other Clusters can reach it to deliver callbacks. 3. **Register Endpoints on every Cluster.** The [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. From 251345f745094bde3791f30a6677e21c8aa34108 Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:38:00 -0700 Subject: [PATCH 53/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index 76d8ee5c6b..f4c9c85e85 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -115,7 +115,7 @@ target an external URL (`--target-url`), which is experimental and not covered h 3. **Register Endpoints on every Cluster.** The [Nexus Endpoint registry](/nexus/registry) isn't replicated across Clusters. - Create the same Endpoints (same target Namespace and Task Queue) on each Cluster. + Create the same Endpoints (same target Namespace and Task Queue) on **each** Cluster. 4. **Cross-Cluster forwarding.** Nexus request and callback forwarding is on by default via `system.enableNamespaceNotActiveAutoForwarding` (per-Namespace From 87a522617eb17a551b735f137c182d353aa4f57e Mon Sep 17 00:00:00 2001 From: Stephan Behnke Date: Fri, 17 Jul 2026 13:38:10 -0700 Subject: [PATCH 54/54] Update temporal-nexus.mdx --- docs/production-deployment/self-hosted-guide/temporal-nexus.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx index f4c9c85e85..12d746eb0d 100644 --- a/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx +++ b/docs/production-deployment/self-hosted-guide/temporal-nexus.mdx @@ -110,7 +110,7 @@ target an external URL (`--target-url`), which is experimental and not covered h 2. **Advertise a frontend HTTP address on every Cluster.** Set `frontend.rpc.httpPort` and `clusterInformation..httpAddress` (shown in - [Enable Nexus](#enable-nexus) for one Cluster) on **every** Cluster, each with its + [Enable Nexus](#enable-nexus) for one Cluster) on **each** Cluster, each with its own address, so the other Clusters can reach it to deliver callbacks. 3. **Register Endpoints on every Cluster.** The