Temporal Namespaces with Go: a roadmap
Why this matters, in 30 seconds
Every Workflow, Task Queue and Worker lives in a Namespace. It decides which Workflow IDs can clash, how long finished Workflows are kept, who can access them and, on Temporal Cloud, which credentials and rate limits apply. Getting Namespaces wrong shows up late:
- A Worker connected to a missing Namespace connects fine and fails only on its first call.
- The retention you pick at registration decides how long finished Workflows can still be debugged.
- A cross-Namespace Child Workflow is rejected by the Service, and the parent stays stuck.
- Deleting a Namespace is instant, irreversible and unguarded, even for
default.
This guide covers these, from the concept to operating Namespaces as code.
The roadmap
Stage 1: Foundations (core concepts, must-know)
| # | Chapter | You'll be able to… |
|---|---|---|
| 01 | What is a Namespace? | Explain what a Namespace isolates, what default is, and why a shared Namespace still needs naming rules. |
| 02 | Using a Namespace from Go | Point Clients and Workers at a Namespace, catch a missing one at startup, and use several Namespaces over one connection. |
Stage 2: Daily use (creating and managing Namespaces)
| # | Chapter | You'll be able to… |
|---|---|---|
| 03 | Registering a Namespace | Create a Namespace with the CLI or Go, choose a retention, make it idempotent, and wait until it's usable. |
| 04 | Describing, updating and listing Namespaces | Read and change a Namespace's settings, list Namespaces, and know what each API can and can't change. |
Stage 3: Advanced (retiring Namespaces)
| # | Chapter | You'll be able to… |
|---|---|---|
| 05 | Deprecating and deleting Namespaces | Retire a Namespace safely: deprecate, drain, delete, and protect the ones that must never go. |
Stage 4: Production
| # | Chapter | You'll be able to… |
|---|---|---|
| 06 | Designing your Namespaces | Decide how to split Namespaces, call across them the supported way, control access, and manage Namespaces as code. |
Core concepts vs. implementation details
| Core concepts: understand these first | Implementation details, options & sub-features: learn when needed |
|---|---|
| A Namespace is a unit of isolation (01) | OSS vs Cloud extras (01) |
| Workflow IDs are unique per Namespace (01) | ID and Task Queue prefixes in a shared Namespace (06) |
| A Client and its Workers use one Namespace (02) | TEMPORAL_NAMESPACE, NewClientFromExisting, startup guard (02) |
| A Namespace must be registered, with a retention (03) | Idempotent registration, propagation delay (03) |
| Settings are per Namespace (04) | Update semantics, listing, per-Namespace Search Attributes and archival (04) |
| Registered → Deprecated → Deleted (05) | Deletion rename, guarded retirement (05) |
| Namespaces don't call each other directly (06) | Activity + second Client, Nexus, Namespaces as code (06) |
Which Namespace setup do I need?
text
Starting out, one service, local dev? → "default" (or start-dev --namespace …) → chapters 01, 02
Several environments (dev / staging / prod)? → one Namespace per environment → chapter 06
Several teams or bounded contexts?
├── Different retention, access or blast radius → one Namespace each → chapter 06
└── Same everything → share one, prefix IDs and Task Queues → chapter 06
Must a Workflow call into another Namespace?
├── Simple request/response → an Activity with a second Client → chapter 06
└── A contract between teams → Nexus → chapter 06
Creating Namespaces from code or CI? → idempotent Ensure / Reconcile, retry NotFound → chapters 03, 06
Retiring a Namespace? → deprecate, drain, then delete (guarded) → chapter 05
On Temporal Cloud? → Cloud UI or `temporal cloud namespace`, not NamespaceClient → chapter 03Go API cheat sheet
| I want to… | Go API | Chapter |
|---|---|---|
| Connect to a Namespace | client.Dial(client.Options{Namespace: "shop-prod"}), or TEMPORAL_NAMESPACE with envconfig | 02 |
| Fail fast if it doesn't exist | nc.Describe(ctx, name) at startup (Dial doesn't check) | 02 |
| Second Namespace, same connection | client.NewClientFromExisting(c, client.Options{Namespace: …}) | 02, 06 |
| Know the current Namespace in a Workflow | workflow.GetInfo(ctx).Namespace | 01 |
| Get a Namespace client | client.NewNamespaceClient(client.Options{…}) | 03 |
| Register | nc.Register(ctx, &workflowservice.RegisterNamespaceRequest{Namespace, WorkflowExecutionRetentionPeriod: durationpb.New(…)}) | 03 |
| Detect "already exists" | errors.As(err, new(*serviceerror.NamespaceAlreadyExists)) | 03 |
| Describe | nc.Describe(ctx, name) | 04 |
| Change retention / description | nc.Update(ctx, &workflowservice.UpdateNamespaceRequest{UpdateInfo: …, Config: …}) | 04 |
| List | c.WorkflowService().ListNamespaces(ctx, &workflowservice.ListNamespacesRequest{PageSize, NextPageToken}) | 04 |
| Deprecate | nc.Update(…, UpdateInfo: &namespacepb.UpdateNamespaceInfo{State: enumspb.NAMESPACE_STATE_DEPRECATED}) | 05 |
| Delete | c.OperatorService().DeleteNamespace(ctx, &operatorservice.DeleteNamespaceRequest{Namespace: …}) | 05 |
| Call another Namespace | an Activity holding a Client for that Namespace, or Nexus | 06 |
About the code samples
- Each chapter is a self-contained module named
github.com/acme/shop. Every Go block starts with// file: <path>so you can paste it into that path. - All samples were compiled,
gofmt-checked andgo vet-checked against Go SDK v1.50.0 (go.temporal.io/sdk) andgo.temporal.io/sdk/contrib/envconfigv1.0.2. - Every behavior was run on a dev server (Temporal CLI 1.9.1, Server 1.32.0): the same Workflow ID in two Namespaces, connecting to a missing Namespace, registration errors and timing,
Updatesemantics, per-Namespace Search Attributes, deprecation, deletion, a Worker whose Namespace is deleted, the rejected cross-Namespace Child Workflow, and the cross-Namespace Activity. - The Namespace admin APIs (
NamespaceClient,OperatorService) work on a self-hosted Service only. On Temporal Cloud, use the Cloud UI ortemporal cloud namespace. - Run everything locally with
temporal server start-dev(UI at http://localhost:8233).
Notes from checking the docs against the SDK
- The SDK can't do everything the page lists. The Go page says you can "create, update, deprecate, or delete" Namespaces with SDK APIs.
NamespaceClienthas onlyRegister,DescribeandUpdate. Listing and deleting go through the rawWorkflowService()andOperatorService(), and deprecating is anUpdateof the state (chapter 04). DeprecateNamespaceis itself deprecated. The RPC still works but is marked "Deprecated." in the API; setState: NAMESPACE_STATE_DEPRECATEDwithUpdateinstead (chapter 05).- Minimum retention. The page says the minimum is 1 day. The dev server accepted 1 hour through the API and the CLI: the minimum is a server setting. The API requires a retention (
InvalidArgumentwithout one), but the CLI fills in 72h when--retentionis omitted (chapter 03). - "Up to 10 seconds". A brand-new Namespace was usable within about 60 ms on a dev server. A name that had been looked up before it existed returned
NamespaceNotFoundfor 0.3–1 s afterRegister, and multi-node clusters add cache delay. RetryNamespaceNotFoundbriefly instead of sleeping (chapter 03). Dialdoesn't check the Namespace.Dial,DialContextandCheckHealthsucceed for a missing Namespace; the first real call returnsNamespaceNotFound(chapter 02).NewNamespaceClientignoresOptions.Namespace(internal/client.go). Every call names its Namespace explicitly (chapter 03).Updateonly adds. Empty strings are ignored,Datais merged, and an emptyConfigchanges nothing: you can't clear a value (chapter 04).- Deprecation is one-way and not instant. Deprecated → Registered is rejected (
Invalid namespace state update). New starts were refused about 2 s after deprecating; one made right after still went through. Running Workflows kept working and received Signals (chapter 05). - Setting the state to Deleted isn't a delete. It hides the Namespace and refuses starts, but
Describestill finds it. UseDeleteNamespace(chapter 05). - Deletion is unguarded. The dev server deleted
defaultwith no confirmation. A deleted Namespace is renamed<name>-deleted-<suffix>and the name can be reused seconds later (chapter 05). - Workers don't notice a deleted Namespace. A Worker kept polling with no error and no
OnFatalErrorfor 30 s+ (chapter 05). - Cross-Namespace Child Workflows are rejected.
ChildWorkflowOptions.Namespaceis deprecated (disabled by default since Server 1.30.1). The parent's Workflow Task failed with "cross namespace commands are not allowed" and the Workflow stayed Running (chapter 06). - The Go page's Update sample uses a
replicationalias without its import (go.temporal.io/api/replication/v1) and mostly commented-out fields (chapter 04).
Sources
Encyclopedia: Temporal Namespace
Go SDK: Namespaces