What is a Domain?
A domain is a logical namespace that provides isolation and organizational boundaries in Cadence. All workflow executions, activities, and task lists belong to a specific domain.
Think of domains as separate workspaces - similar to Kubernetes namespaces or AWS accounts. Each domain has its own workflows, task lists, and configuration.
Why Domains Matter
Domains provide several critical capabilities:
Isolation : Workflows in different domains are completely isolated
Multi-tenancy : Support multiple teams or customers on the same cluster
Environment Separation : Different domains for dev, staging, and production
Security : Control access at the domain level
Configuration : Different retention policies and settings per domain
Failover : Cross-region replication for disaster recovery
Domain Structure
DomainInfo
type DomainInfo struct {
Name string `json:"name,omitempty"`
Status * DomainStatus `json:"status,omitempty"`
Description string `json:"description,omitempty"`
OwnerEmail string `json:"ownerEmail,omitempty"`
Data map [ string ] string `json:"data,omitempty"`
UUID string `json:"uuid,omitempty"`
}
Name : Unique domain identifier (e.g., “production-orders”)
Status : Domain state (REGISTERED, DEPRECATED, DELETED)
Description : Human-readable description
OwnerEmail : Contact information for domain owner
Data : Key-value metadata
UUID : System-generated unique identifier
DomainStatus
type DomainStatus int32
const (
DomainStatusRegistered DomainStatus = iota // Active and accepting workflows
DomainStatusDeprecated // No new workflows, existing continue
DomainStatusDeleted // Marked for deletion
)
DomainConfiguration
type DomainConfiguration struct {
WorkflowExecutionRetentionPeriodInDays int32
EmitMetric bool
HistoryArchivalStatus ArchivalStatus
HistoryArchivalURI string
VisibilityArchivalStatus ArchivalStatus
VisibilityArchivalURI string
BadBinaries * BadBinaries
IsolationGroups * IsolationGroupConfiguration
AsyncWorkflowConfig * AsyncWorkflowConfiguration
}
How Domains Work Internally
Domain Registration
When you register a domain:
Validation : Name is checked for uniqueness and format
Persistence : Domain metadata is stored in the system
Replication : Domain info is replicated to all clusters (if configured)
Cache : Domain is loaded into the domain cache
Ready : Domain is now available for workflow executions
Domain Cache
Cadence maintains an in-memory cache of domain metadata:
type DomainCacheInfo struct {
ID string
Name string
Status DomainStatus
Description string
OwnerEmail string
Data map [ string ] string
RetentionDays int32
// ... other fields
}
The cache provides:
Fast domain lookups
Configuration access
Replication state
Cross-Region Replication
For global domains:
type DomainReplicationConfiguration struct {
ActiveClusterName string
Clusters [] * ClusterReplicationConfiguration
}
Code Examples
Go - Register Domain
Go - Update Domain
Go - Describe Domain
CLI
package main
import (
" context "
" go.uber.org/cadence/client "
)
func main () {
// Create admin client
domainClient , err := client . NewDomainClient (
client . Options { HostPort : "localhost:7933" },
)
if err != nil {
panic ( err )
}
defer domainClient . Close ()
// Register a domain
err = domainClient . Register ( context . Background (), & client . RegisterDomainRequest {
Name : "production-orders" ,
Description : "Production order processing workflows" ,
OwnerEmail : "[email protected] " ,
WorkflowExecutionRetentionPeriodInDays : 7 ,
EmitMetric : true ,
Data : map [ string ] string {
"team" : "payments" ,
"environment" : "production" ,
},
})
if err != nil {
panic ( err )
}
}
func updateDomain () {
// Update domain configuration
err := domainClient . Update ( context . Background (), & client . UpdateDomainRequest {
Name : "production-orders" ,
UpdatedInfo : & client . UpdateDomainInfo {
Description : "Updated description" ,
OwnerEmail : "[email protected] " ,
Data : map [ string ] string {
"team" : "checkout" ,
"cost-center" : "cc-1234" ,
},
},
Configuration : & client . DomainConfiguration {
WorkflowExecutionRetentionPeriodInDays : 14 ,
EmitMetric : true ,
HistoryArchivalStatus : client . ArchivalStatusEnabled ,
HistoryArchivalURI : "s3://my-bucket/history" ,
},
})
if err != nil {
panic ( err )
}
}
func describeDomain () {
// Get domain information
resp , err := domainClient . Describe ( context . Background (), "production-orders" )
if err != nil {
panic ( err )
}
fmt . Printf ( "Domain: %s \n " , resp . DomainInfo . Name )
fmt . Printf ( "UUID: %s \n " , resp . DomainInfo . UUID )
fmt . Printf ( "Status: %s \n " , resp . DomainInfo . Status )
fmt . Printf ( "Retention: %d days \n " , resp . Configuration . WorkflowExecutionRetentionPeriodInDays )
fmt . Printf ( "Owner: %s \n " , resp . DomainInfo . OwnerEmail )
// Check if domain is global
if resp . ReplicationConfiguration != nil {
fmt . Printf ( "Active Cluster: %s \n " , resp . ReplicationConfiguration . ActiveClusterName )
}
}
# Register a domain
cadence --domain production-orders domain register \
--description "Production order workflows" \
--owner-email [email protected] \
--retention 7
# Describe a domain
cadence --domain production-orders domain describe
# Update domain
cadence --domain production-orders domain update \
--retention 14 \
--owner-email [email protected]
# List all domains
cadence domain list
# Deprecate a domain
cadence --domain old-domain domain update --status deprecated
Domain Configuration
Retention Policies
// Workflow execution retention period
type DomainConfiguration struct {
WorkflowExecutionRetentionPeriodInDays int32
}
Retention Period determines how long closed workflow histories are kept:
Minimum: 1 day
Maximum: Configurable (typically 30 days)
After retention: History is archived or deleted
Archival Configuration
type ArchivalStatus int32
const (
ArchivalStatusDisabled ArchivalStatus = iota
ArchivalStatusEnabled
)
History Archival
Visibility Archival
domainClient . Register ( context . Background (), & client . RegisterDomainRequest {
Name : "archived-domain" ,
Configuration : & client . DomainConfiguration {
HistoryArchivalStatus : client . ArchivalStatusEnabled ,
HistoryArchivalURI : "s3://my-bucket/history-archive" ,
},
})
domainClient . Register ( context . Background (), & client . RegisterDomainRequest {
Name : "archived-domain" ,
Configuration : & client . DomainConfiguration {
VisibilityArchivalStatus : client . ArchivalStatusEnabled ,
VisibilityArchivalURI : "s3://my-bucket/visibility-archive" ,
},
})
Best Practices
1. Domain Naming Conventions
Good Examples
Bad Examples
production-orders
staging-payments
dev-user-workflows
customer-acme-prod
2. Environment Separation
// Development domain
domainClient . Register ( ctx , & client . RegisterDomainRequest {
Name : "dev-orders" ,
Description : "Development environment" ,
WorkflowExecutionRetentionPeriodInDays : 1 , // Short retention
EmitMetric : false , // Disable metrics
})
// Production domain
domainClient . Register ( ctx , & client . RegisterDomainRequest {
Name : "prod-orders" ,
Description : "Production environment" ,
WorkflowExecutionRetentionPeriodInDays : 30 , // Long retention
EmitMetric : true , // Enable metrics
HistoryArchivalStatus : client . ArchivalStatusEnabled , // Archive histories
})
3. Multi-Tenancy
// Separate domain per customer
for _ , customer := range customers {
domainClient . Register ( ctx , & client . RegisterDomainRequest {
Name : fmt . Sprintf ( "customer- %s " , customer . ID ),
Description : fmt . Sprintf ( "Workflows for %s " , customer . Name ),
OwnerEmail : customer . Email ,
Data : map [ string ] string {
"customer-id" : customer . ID ,
"customer-tier" : customer . Tier ,
},
})
}
4. Domain Metadata
// Use Data field for custom metadata
domainClient . Register ( ctx , & client . RegisterDomainRequest {
Name : "production-orders" ,
Data : map [ string ] string {
"team" : "payments" ,
"cost-center" : "cc-1234" ,
"environment" : "production" ,
"region" : "us-west-2" ,
"slack-channel" : "#team-payments" ,
"oncall" : "[email protected] " ,
},
})
5. Global Domains for Failover
// Register global domain with replication
domainClient . Register ( ctx , & client . RegisterDomainRequest {
Name : "global-orders" ,
IsGlobalDomain : true ,
ActiveClusterName : "us-west-2" ,
Clusters : [] * client . ClusterReplicationConfiguration {
{ ClusterName : "us-west-2" },
{ ClusterName : "us-east-1" },
{ ClusterName : "eu-west-1" },
},
})
// Failover to different cluster
domainClient . Update ( ctx , & client . UpdateDomainRequest {
Name : "global-orders" ,
ReplicationConfiguration : & client . DomainReplicationConfiguration {
ActiveClusterName : "eu-west-1" , // Failover to EU
},
})
Domain Lifecycle
Active State
type DomainInfo struct {
Status * DomainStatus // DomainStatusRegistered
}
Accepts new workflow executions
All operations are allowed
Normal operation mode
Deprecated State
// Deprecate a domain
domainClient . Update ( ctx , & client . UpdateDomainRequest {
Name : "old-domain" ,
UpdatedInfo : & client . UpdateDomainInfo {
Status : client . DomainStatusDeprecated ,
},
})
No new workflow executions allowed
Existing workflows continue
Use for graceful domain shutdown
Deleted State
Domain Deletion is Permanent : Once deleted, all workflow histories and data are lost. Use deprecation instead for graceful shutdown.
Domain Errors
DomainNotActiveError
type DomainNotActiveError struct {
Message string
DomainName string
CurrentCluster string
ActiveCluster string
ActiveClusters [] string
}
Thrown when:
Accessing a global domain from non-active cluster
Domain is in process of failing over
Requires redirect to active cluster
DomainAlreadyExistsError
type DomainAlreadyExistsError struct {
Message string
}
Thrown when:
Attempting to register domain with existing name
Domain name conflicts with deleted domain
Domain Isolation Groups
Isolation groups allow routing workflows to specific worker pools within a domain:
type IsolationGroupConfiguration struct {
IsolationGroups [] * IsolationGroupPartition
}
type IsolationGroupPartition struct {
Name string
State IsolationGroupState
}
Use cases:
GPU vs CPU workloads
High vs low priority
Different SLA tiers
Monitoring and Observability
Domain Metrics
domainClient . Register ( ctx , & client . RegisterDomainRequest {
Name : "monitored-domain" ,
EmitMetric : true , // Enable metric emission
})
Key metrics:
cadence_workflow_started
cadence_workflow_completed
cadence_workflow_failed
cadence_workflow_timeout
cadence_activity_started
Domain Filter
Filter operations by domain:
type DomainFilter struct {
DomainIDs [] string
ReverseMatch bool
}
Workflows - Execute workflows within domains
Task Lists - Task lists are scoped to domains
Workers - Workers connect to specific domains
Archival - Configure domain-level archival
Further Reading