Skip to content

Commit cd08a0a

Browse files
feat(demo): add Temporal High Availability interactive demo
Adds a new interactive demo page at /ha-demo covering Temporal Cloud High Availability -- same-region, multi-region, and multi-cloud replication -- following the same section-based format as the Nexus demo (PR #4332). New files: - docs/ha-demo.mdx: MDX entry point at /ha-demo - src/components/HADemo/index.tsx: nav + section switcher - src/components/HADemo/Overview.tsx: What is HA, SLA comparison table - src/components/HADemo/ReplicationTypes.tsx: 3 replication types + failure coverage matrix - src/components/HADemo/HowItWorks.tsx: animated replication/failover flow - src/components/HADemo/FailoverSection.tsx: Hybrid/Graceful/Forced tabs, trigger methods - src/components/HADemo/EnableIt.tsx: tcld + UI setup steps for all HA operations - src/components/HADemo/Quiz.tsx: 6-question quiz with score card + resource links - src/components/HADemo/HADemo.module.css: IFM-variable-based light/dark styles - src/components/HADemo/replicationSteps.ts: animated flow step data - src/components/HADemo/quizQuestions.ts: quiz question data sidebars.js updated to add an 'Interactive Demos' category. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d60a2ef commit cd08a0a

12 files changed

Lines changed: 2643 additions & 0 deletions

docs/ha-demo.mdx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
id: ha-demo
3+
title: Temporal High Availability - Interactive Demo
4+
sidebar_label: High Availability
5+
description: An interactive walkthrough of Temporal Cloud High Availability — what it is, how replication works, and how to enable it.
6+
slug: /ha-demo
7+
tags:
8+
- High Availability
9+
- Cloud
10+
keywords:
11+
- temporal high availability demo
12+
- same-region replication
13+
- multi-region replication
14+
- failover
15+
- RPO RTO
16+
hide_table_of_contents: true
17+
---
18+
19+
import HADemo from '@site/src/components/HADemo';
20+
21+
<HADemo />

sidebars.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,15 @@ module.exports = {
890890
],
891891
},
892892
'glossary',
893+
{
894+
type: 'category',
895+
label: 'Interactive Demos',
896+
collapsed: true,
897+
items: [
898+
// 'nexus-demo', // added in PR #4332
899+
'ha-demo',
900+
],
901+
},
893902
'with-ai',
894903
// {
895904
// type: "autogenerated",

src/components/HADemo/EnableIt.tsx

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
import React, { useState } from 'react';
2+
import styles from './HADemo.module.css';
3+
4+
type Props = { onNext: () => void };
5+
type Tab = 'create' | 'add' | 'remove';
6+
7+
const TABS: { id: Tab; label: string }[] = [
8+
{ id: 'create', label: 'Create with HA' },
9+
{ id: 'add', label: 'Add replica to existing' },
10+
{ id: 'remove', label: 'Remove replica' },
11+
];
12+
13+
function Cmd({ prompt, cmd }: { prompt: string; cmd: string }) {
14+
return (
15+
<div className={styles.cmdBlock}>
16+
<span className={styles.cmdPrompt}>{prompt}&nbsp;</span>
17+
<span className={styles.cmdText}>{cmd}</span>
18+
</div>
19+
);
20+
}
21+
22+
export default function EnableIt({ onNext }: Props) {
23+
const [tab, setTab] = useState<Tab>('create');
24+
25+
return (
26+
<div className={styles.section}>
27+
<div className={styles.progressBar}>
28+
<div className={styles.progressFill} style={{ width: '71%' }} />
29+
</div>
30+
31+
<h1>Enable High Availability</h1>
32+
<p className={styles.lead}>
33+
You can add a replica when creating a new Namespace or at any time on an existing one.
34+
Both the Web UI and <code>tcld</code> CLI are supported.
35+
</p>
36+
37+
<div className={styles.runTabs}>
38+
{TABS.map((t) => (
39+
<button
40+
key={t.id}
41+
className={`${styles.runTab} ${tab === t.id ? styles.runTabActive : ''}`}
42+
onClick={() => setTab(t.id)}
43+
>
44+
{t.label}
45+
</button>
46+
))}
47+
</div>
48+
49+
{/* ── Create with HA ── */}
50+
{tab === 'create' && (
51+
<>
52+
<div className={styles.card} style={{ marginBottom: 20 }}>
53+
<div className={`${styles.tag} ${styles.tagBlue}`}>New Namespace</div>
54+
<p style={{ fontSize: 13, color: 'var(--hd-muted)', margin: '0 0 0' }}>
55+
Specify both a primary region and a replica region when creating the Namespace.
56+
Temporal Cloud immediately begins replicating all new Workflow history to the replica.
57+
</p>
58+
</div>
59+
60+
<div className={styles.enableSectionLabel}>Via tcld</div>
61+
<Cmd
62+
prompt="$"
63+
cmd={`tcld namespace create \\
64+
--namespace <namespace_id>.<account_id> \\
65+
--region <primary_region> \\
66+
--region <replica_region>`}
67+
/>
68+
<div className={styles.cmdOutput}>
69+
# Example (multi-region, GA):
70+
# --region aws-us-east-1 --region aws-us-west-2
71+
</div>
72+
73+
<div className={styles.enableSectionLabel}>Via Web UI</div>
74+
<div className={styles.failoverSteps}>
75+
<div className={styles.failoverStep}>
76+
<div className={styles.failoverStepNum}>1</div>
77+
<div>
78+
<div className={styles.failoverStepText}>Navigate to Temporal Cloud and click <strong>Create Namespace</strong></div>
79+
</div>
80+
</div>
81+
<div className={styles.failoverStep}>
82+
<div className={styles.failoverStepNum}>2</div>
83+
<div>
84+
<div className={styles.failoverStepText}>Select the <strong>primary region</strong></div>
85+
<div className={styles.failoverStepNote}>e.g. AWS us-east-1</div>
86+
</div>
87+
</div>
88+
<div className={styles.failoverStep}>
89+
<div className={styles.failoverStepNum}>3</div>
90+
<div>
91+
<div className={styles.failoverStepText}>Click <strong>"Add a replica"</strong> and choose the replica region</div>
92+
<div className={styles.failoverStepNote}>
93+
Same-region and multi-cloud are in Public Preview; multi-region is GA.
94+
</div>
95+
</div>
96+
</div>
97+
<div className={styles.failoverStep}>
98+
<div className={styles.failoverStepNum}>4</div>
99+
<div>
100+
<div className={styles.failoverStepText}>Confirm and create</div>
101+
<div className={styles.failoverStepNote}>
102+
Replication begins immediately for all new and existing Workflow Executions.
103+
</div>
104+
</div>
105+
</div>
106+
</div>
107+
</>
108+
)}
109+
110+
{/* ── Add to existing ── */}
111+
{tab === 'add' && (
112+
<>
113+
<div className={styles.card} style={{ marginBottom: 20 }}>
114+
<div className={`${styles.tag} ${styles.tagGreen}`}>Existing Namespace</div>
115+
<p style={{ fontSize: 13, color: 'var(--hd-muted)', margin: 0 }}>
116+
You can add a replica to an existing Namespace at any time. Temporal Cloud begins
117+
asynchronously replicating <strong>all ongoing and historical</strong> Workflow
118+
Executions to the new replica.
119+
</p>
120+
</div>
121+
122+
<div className={styles.enableSectionLabel}>Via tcld</div>
123+
<Cmd
124+
prompt="$"
125+
cmd={`tcld namespace add-region \\
126+
--namespace <namespace_id>.<account_id> \\
127+
--region <replica_region>`}
128+
/>
129+
130+
<div className={styles.enableSectionLabel}>Via Web UI</div>
131+
<div className={styles.failoverSteps}>
132+
<div className={styles.failoverStep}>
133+
<div className={styles.failoverStepNum}>1</div>
134+
<div>
135+
<div className={styles.failoverStepText}>
136+
Go to your Namespace detail page in Temporal Cloud
137+
</div>
138+
</div>
139+
</div>
140+
<div className={styles.failoverStep}>
141+
<div className={styles.failoverStepNum}>2</div>
142+
<div>
143+
<div className={styles.failoverStepText}>
144+
Click <strong>"Add a replica"</strong>
145+
</div>
146+
</div>
147+
</div>
148+
<div className={styles.failoverStep}>
149+
<div className={styles.failoverStepNum}>3</div>
150+
<div>
151+
<div className={styles.failoverStepText}>
152+
Select the desired replica region and confirm
153+
</div>
154+
<div className={styles.failoverStepNote}>
155+
Replication of existing history begins immediately.
156+
</div>
157+
</div>
158+
</div>
159+
</div>
160+
161+
<div className={styles.enableNote}>
162+
<span className={styles.enableNoteIcon}>ℹ️</span>
163+
<span>
164+
<strong>Changing replica location:</strong> Direct migration of a replica to a
165+
different region is not supported. Remove the existing replica first, then add a new
166+
one in the desired location. You must wait <strong>7 days</strong> before re-enabling
167+
HA in the same region after removal.
168+
</span>
169+
</div>
170+
</>
171+
)}
172+
173+
{/* ── Remove replica ── */}
174+
{tab === 'remove' && (
175+
<>
176+
<div className={styles.card} style={{ marginBottom: 20 }}>
177+
<div className={`${styles.tag} ${styles.tagAmber}`}>Disable HA</div>
178+
<p style={{ fontSize: 13, color: 'var(--hd-muted)', margin: 0 }}>
179+
Removing a replica disables replication and reduces the Namespace back to a standard
180+
single-isolation-domain configuration. The 7-day cooldown applies before you can
181+
re-add a replica in the same location.
182+
</p>
183+
</div>
184+
185+
<div className={styles.enableSectionLabel}>Via tcld</div>
186+
<Cmd
187+
prompt="$"
188+
cmd={`tcld namespace delete-region \\
189+
--api-key <api_key> \\
190+
--namespace <namespace_id>.<account_id> \\
191+
--region <replica_region_name>`}
192+
/>
193+
194+
<div className={styles.enableSectionLabel}>Via Web UI</div>
195+
<div className={styles.failoverSteps}>
196+
<div className={styles.failoverStep}>
197+
<div className={styles.failoverStepNum}>1</div>
198+
<div>
199+
<div className={styles.failoverStepText}>
200+
Go to your Namespace detail page
201+
</div>
202+
</div>
203+
</div>
204+
<div className={styles.failoverStep}>
205+
<div className={styles.failoverStepNum}>2</div>
206+
<div>
207+
<div className={styles.failoverStepText}>
208+
Find the replica entry and click <strong>"Remove replica"</strong>
209+
</div>
210+
</div>
211+
</div>
212+
<div className={styles.failoverStep}>
213+
<div className={styles.failoverStepNum}>3</div>
214+
<div>
215+
<div className={styles.failoverStepText}>Confirm the removal</div>
216+
<div className={styles.failoverStepNote}>
217+
The Namespace reverts to standard configuration. SLA reverts to 99.9%.
218+
</div>
219+
</div>
220+
</div>
221+
</div>
222+
223+
<div className={styles.enableNote}>
224+
<span className={styles.enableNoteIcon}>⚠️</span>
225+
<span>
226+
<strong>7-day cooldown:</strong> After removing a replica, you cannot re-enable HA
227+
in the same location for 7 days. Plan replica migrations carefully — remove first,
228+
add the new location, then remove the old one if needed.
229+
</span>
230+
</div>
231+
</>
232+
)}
233+
234+
<h2 className={styles.sectionHeading}>Monitoring Replication Health</h2>
235+
<div className={styles.cardGrid} style={{ gridTemplateColumns: 'repeat(2, 1fr)' }}>
236+
<div className={styles.card}>
237+
<div className={`${styles.tag} ${styles.tagBlue}`}>Cloud UI</div>
238+
<p style={{ fontSize: 13, color: 'var(--ifm-font-color-base)', margin: '0 0 8px', lineHeight: 1.6 }}>
239+
The Temporal Cloud UI displays replica status and health. When a replica becomes
240+
unhealthy, failover options are automatically disabled to prevent cascading issues.
241+
</p>
242+
</div>
243+
<div className={styles.card}>
244+
<div className={`${styles.tag} ${styles.tagPurple}`}>Metrics</div>
245+
<p style={{ fontSize: 13, color: 'var(--ifm-font-color-base)', margin: '0 0 8px', lineHeight: 1.6 }}>
246+
Replication lag is emitted as pre-computed percentiles (p50, p95, p99) on the metric{' '}
247+
<code>temporal_cloud_v0_replication_lag_bucket</code>, labeled with{' '}
248+
<code>temporal_namespace</code>. Target: p95 &lt; 1 minute.
249+
</p>
250+
<p style={{ fontSize: 12, color: 'var(--hd-muted)', margin: 0, lineHeight: 1.5 }}>
251+
Note: <code>temporal_cloud_v1_total_action_count</code> may appear doubled for HA
252+
Namespaces — actions are replicated on both primary and replica.
253+
</p>
254+
</div>
255+
</div>
256+
257+
<div className={styles.nextRow}>
258+
<button className={styles.btn} onClick={onNext}>
259+
Next: Test Yourself →
260+
</button>
261+
</div>
262+
</div>
263+
);
264+
}

0 commit comments

Comments
 (0)