Temporal — API Surface#
API types#
Multiple, layered: gRPC (public + internal), REST/HTTP (via grpc-gateway proxy), Nexus HTTP, CLI (urfave/cli), and a Go embedding library.
gRPC API#
Temporal exposes three tiers of gRPC APIs:
Tier 1: Public client-facing services (defined in go.temporal.io/api — external module)#
These are the services that application developers and SDK clients interact with. Both are registered on the Frontend Service’s public gRPC listener.
WorkflowService (go.temporal.io/api/workflowservice/v1)#
The primary public API — ~60 RPCs covering the complete workflow lifecycle:
Namespace management:
RegisterNamespace,DescribeNamespace,ListNamespaces,UpdateNamespace,DeprecateNamespace
Workflow lifecycle:
StartWorkflowExecution,ExecuteMultiOperationDescribeWorkflowExecution,RequestCancelWorkflowExecutionTerminateWorkflowExecution,DeleteWorkflowExecutionResetWorkflowExecution,SignalWorkflowExecution,SignalWithStartWorkflowExecutionQueryWorkflow,UpdateWorkflowExecution,PollWorkflowExecutionUpdateGetWorkflowExecutionHistory,GetWorkflowExecutionHistoryReverseUpdateWorkflowExecutionOptions(versioning override)PauseWorkflowExecution,UnpauseWorkflowExecution
Worker polling (SDK internal):
PollWorkflowTaskQueue,RespondWorkflowTaskCompleted,RespondWorkflowTaskFailedPollActivityTaskQueue,RecordActivityTaskHeartbeat,RecordActivityTaskHeartbeatByIdRespondActivityTaskCompleted,RespondActivityTaskCompletedByIdRespondActivityTaskFailed,RespondActivityTaskFailedByIdRespondActivityTaskCanceled,RespondActivityTaskCanceledByIdRespondQueryTaskCompleted,ResetStickyTaskQueue
Activity management (new):
UpdateActivityOptions,PauseActivity,UnpauseActivity,ResetActivity
Visibility / search:
ListWorkflowExecutions,ListOpenWorkflowExecutions,ListClosedWorkflowExecutionsListArchivedWorkflowExecutions,ScanWorkflowExecutions,CountWorkflowExecutionsGetSearchAttributes
Schedule management:
CreateSchedule,DescribeSchedule,UpdateSchedule,DeleteSchedulePatchSchedule,ListSchedules,ListScheduleMatchingTimes
Task queue:
DescribeTaskQueue,ListTaskQueuePartitions,ResetStickyTaskQueueUpdateWorkerBuildIdCompatibility,GetWorkerBuildIdCompatibilityUpdateWorkerVersioningRules,GetWorkerVersioningRulesGetWorkerTaskReachability,ShutdownWorkerUpdateTaskQueueConfig,FetchWorkerConfig,UpdateWorkerConfig
Batch operations:
StartBatchOperation,StopBatchOperation,DescribeBatchOperation,ListBatchOperations
Worker deployment:
RecordWorkerHeartbeat,ListWorkers,DescribeWorker
Nexus task polling (SDK internal):
PollNexusTaskQueue,RespondNexusTaskCompleted,RespondNexusTaskFailed
Workflow rules (experimental):
CreateWorkflowRule,DescribeWorkflowRule,DeleteWorkflowRule,ListWorkflowRules,TriggerWorkflowRule
Cluster info:
GetClusterInfo,GetSystemInfo
OperatorService (go.temporal.io/api/operatorservice/v1)#
Cluster administration operations, also served on the Frontend’s public gRPC port:
AddSearchAttributes,RemoveSearchAttributes,ListSearchAttributesDeleteNamespaceAddOrUpdateRemoteCluster,RemoveRemoteCluster,ListClustersCreateNexusEndpoint,UpdateNexusEndpoint,DeleteNexusEndpoint,GetNexusEndpoint,ListNexusEndpoints
Tier 2: Internal server-to-server services (defined in proto/internal/ in this repo)#
These are not exposed to clients; they use internal gRPC on separate ports and carry no auth.
HistoryService (api/historyservice/v1) — ~55 RPCs#
The core shard-level execution engine API. All workflow state mutations flow through here from Frontend:
- Workflow task/activity lifecycle:
StartWorkflowExecution,RecordWorkflowTaskStarted,RecordActivityTaskStarted,RespondWorkflowTaskCompleted,RespondActivityTask* - Signals/queries:
SignalWorkflowExecution,QueryWorkflow,UpdateWorkflowExecution,PollWorkflowExecutionUpdate - History access:
GetWorkflowExecutionHistory,GetWorkflowExecutionHistoryReverse,GetWorkflowExecutionRawHistory,GetWorkflowExecutionRawHistoryV2 - Replication:
ReplicateEventsV2,ReplicateWorkflowState,SyncShardStatus,SyncActivity,StreamWorkflowReplicationMessages(bidirectional streaming) - DLQ/task management:
GetDLQMessages,PurgeDLQMessages,MergeDLQMessages,GetDLQTasks,DeleteDLQTasks,AddTasks,ListTasks - New CHASM operations:
CompleteNexusOperation,CompleteNexusOperationChasm,InvokeStateMachineMethod,StartNexusOperation,CancelNexusOperation - Activity control:
PauseActivity,UnpauseActivity,ResetActivity,UpdateActivityOptions - Workflow control:
PauseWorkflowExecution,UnpauseWorkflowExecution
MatchingService (api/matchingservice/v1) — ~30 RPCs#
Task queue dispatch and worker management:
- Core dispatch:
AddWorkflowTask,AddActivityTask,PollWorkflowTaskQueue,PollActivityTaskQueue - Query:
QueryWorkflow,RespondQueryTaskCompleted - Nexus:
DispatchNexusTask,PollNexusTaskQueue,RespondNexusTaskCompleted,RespondNexusTaskFailed - Task queue management:
DescribeTaskQueue,DescribeTaskQueuePartition,ListTaskQueuePartitions - Worker versioning:
UpdateWorkerBuildIdCompatibility,GetWorkerBuildIdCompatibility,UpdateWorkerVersioningRules,GetWorkerVersioningRules - Nexus endpoint management:
CreateNexusEndpoint,UpdateNexusEndpoint,DeleteNexusEndpoint,ListNexusEndpoints - Worker lifecycle:
CancelOutstandingPoll,CancelOutstandingWorkerPolls,RecordWorkerHeartbeat,ListWorkers,DescribeWorker - Replication:
ApplyTaskQueueUserDataReplicationEvent,ReplicateTaskQueueUserData - Fairness:
UpdateFairnessState
AdminService (api/adminservice/v1) — ~40 RPCs#
Debug and operational tooling, exposed only to admin clients:
- Internal state inspection:
DescribeMutableState,DescribeHistoryHost,GetShard,CloseShard,GetWorkflowExecutionRawHistory* - Replication management:
GetReplicationMessages,GetNamespaceReplicationMessages,GetDLQReplicationMessages,ResendReplicationTasks,StreamWorkflowReplicationMessages - DLQ management:
GetDLQMessages,PurgeDLQMessages,MergeDLQMessages,GetDLQTasks,PurgeDLQTasks,MergeDLQTasks,DescribeDLQJob,CancelDLQJob - Cluster management:
DescribeCluster,ListClusters,ListClusterMembers,AddOrUpdateRemoteCluster,RemoveRemoteCluster - Maintenance:
RebuildMutableState,ImportWorkflowExecution,RefreshWorkflowTasks,DeleteWorkflowExecution,SyncWorkflowState - Admin batch:
StartAdminBatchOperation - Task queue debug:
GetTaskQueueTasks,DescribeTaskQueuePartition,ForceUnloadTaskQueuePartition - Queues:
AddTasks,ListQueues,ListHistoryTasks,RemoveTask - Schedule migration:
MigrateSchedule(V1 workflow → V2 CHASM) - Health:
DeepHealthCheck
Tier 3: CHASM library services (new, in chasm/lib/)#
Proto-defined services for the new CHASM-backed execution model, registered via chasm.Library.RegisterServices(*grpc.Server):
SchedulerService(chasm/lib/scheduler): CHASM-based schedule managementActivityService(chasm/lib/activity): CHASM-based activity executionTestService(chasm/lib/tests): Test infrastructure
REST/HTTP API#
- Router:
gorilla/muxas the outer router;grpc-gateway v2(github.com/grpc-ecosystem/grpc-gateway/v2/runtime.ServeMux) as the inner handler - Implementation:
HTTPAPIServer(service/frontend/http_api_server.go) listens on a separate port (configurable viarpcConfig.HTTPPort). Requests are bridged to gRPC via an inline client connection (newInlineClientConn) that passes through the full gRPC interceptor chain — no network round-trip. - Route registration: Auto-generated from the proto HTTP annotations via grpc-gateway. Routes map 1:1 to
WorkflowServiceandOperatorServicemethods. The custom Nexus routes and OpenAPI handler take precedence via explicit gorilla/mux registration. - Services registered:
WorkflowService→workflowservice.RegisterWorkflowServiceHandlerClientOperatorService→operatorservice.RegisterOperatorServiceHandlerClient
- Content negotiation: Four marshalers in priority order: indented proto-JSON, compact proto-JSON, indented legacy JSON, compact legacy JSON (all custom
temporalProtoMarshaler). - TLS: Optional; uses the same TLS config as the gRPC frontend listener.
- Authentication: Passes through the full gRPC interceptor chain (including auth); the
Authorizationheader is forwarded.
Nexus HTTP API#
Temporal exposes a dedicated HTTP endpoint for Nexus protocol task dispatch (separate from the standard REST gateway):
- Handler:
NexusHTTPHandler(service/frontend/nexus_http_handler.go) - SDK:
github.com/nexus-rpc/sdk-go/nexus— uses the Nexus SDK’s HTTP handler - Routes (via gorilla/mux):
/{namespace}/{task-queue}/...— dispatch by namespace + task queue (legacy)/endpoint/{endpoint}/...— dispatch by Nexus endpoint name
- Protocol: Standard Nexus HTTP protocol. The handler pre-processes requests (endpoint lookup, auth, rate limits) then delegates to the Nexus SDK handler which dispatches to Matching service via
DispatchNexusTask.
gRPC Interceptor Chain (Frontend)#
All frontend gRPC requests (both gRPC and REST-via-gateway) pass through this ordered chain:
TelemetryInterceptor— tracing, metrics tagging, request/response loggingServiceErrorInterceptor— maps internal errors to gRPC status codesFrontendServiceErrorInterceptor— additional frontend-specific error mappingHealthInterceptor— rejects requests when service is not healthyRateLimitInterceptor— global cluster-level rate limitingNamespaceRateLimitInterceptor— per-namespace rate limiting (configurable via dynamic config)ConcurrentRequestLimitInterceptor— per-namespace concurrency limitsNamespaceValidatorInterceptor— validates namespace exists and is activeNamespaceHandoverInterceptor— blocks requests during namespace handover (cross-cluster failover)NamespaceLogInterceptor— structured logging per namespaceBusinessIDInterceptor— extracts workflow/run IDs for structured log contextRedirectionInterceptor— redirects requests to the correct cluster during multi-cluster operationSDKVersionInterceptor— records SDK version from client headers for metricsCallerInfoInterceptor— attaches caller identity (name, version, type) to contextMaskInternalErrorDetailsInterceptor— strips internal error details from external responsesSlowRequestLoggerInterceptor— logs requests that exceed a configurable latency threshold- Custom interceptors (from
WithChainedFrontendGrpcInterceptors) — appended after built-in chain RetryableInterceptor— automatic retries for transient errors (last in chain)
Internal services (History, Matching) have a shorter chain: telemetry, service error, health only.
Authentication#
- Mechanism: Pluggable via
WithAuthorizer(authorization.Authorizer)andWithClaimMapper(func(*config.Config) authorization.ClaimMapper)server options - Default: JWT-based via
go.temporal.io/server/common/authorization. TheClaimMapperextracts claims from the JWT; theAuthorizermakes allow/deny decisions per RPC. - Audience validation: Configurable via
WithAudienceGetter - No-auth mode:
--allow-no-authflag required when no authorizer is configured (a safety gate) - gRPC metadata:
Authorizationheader is passed through from HTTP to gRPC via header forwarding rules
CLI#
- Framework:
urfave/cliv2 - Binary:
temporal-server(built fromcmd/server/main.go) - Commands:
| Command | Description |
|---|---|
start | Start one or more Temporal services |
validate-dynamic-config | Validate dynamic config YAML file(s) against known keys and types |
render-config | Load and render config template to stdout |
Global flags:
--config-file <path>/TEMPORAL_CONFIG_FILE: primary config loading--config <dir>,--env <name>,--zone <name>: legacy config loading (deprecated)--allow-no-auth: permit running without an authorizer
startflags:--service <name>(repeatable) /TEMPORAL_SERVICES: services to start (default: all four)
The CLI is minimal by design — Temporal’s operational surface is dominated by the gRPC/REST APIs, not CLI commands. Operators use tctl (a separate tool) or the Temporal Cloud UI for day-to-day operations.
Go Library API (Embedding)#
Temporal can be embedded in Go programs via the temporal package (go.temporal.io/server/temporal), useful for test servers and development environments.
- Public packages:
temporal(top-level embedding API) - API style: Functional options pattern
Core interface:
type Server interface {
Start() error
Stop() error
}
func NewServer(opts ...ServerOption) (Server, error)Key ServerOption functions:
| Function | Purpose |
|---|---|
WithConfig(*config.Config) | Supply pre-loaded config struct |
WithConfigLoader(dir, env, zone string) | Load config from a directory |
WithServerConfigFilePath(path) | Load config from a single file |
ForServices(names []string) | Select which services to start |
WithStaticHosts(map) | Disable Ringpop; use static addresses |
InterruptOn(<-chan any) | Block Start() until signal received |
WithLogger(log.Logger) | Custom logger |
WithAuthorizer(authorization.Authorizer) | Custom auth plugin |
WithClaimMapper(func(*config.Config) ClaimMapper) | Custom JWT claim extraction |
WithAudienceGetter(func(*config.Config) JWTAudienceMapper) | Custom audience validation |
WithTLSConfigFactory(TLSConfigProvider) | Custom TLS |
WithDynamicConfigClient(dynamicconfig.Client) | Custom dynamic config backend |
WithCustomDataStoreFactory(AbstractDataStoreFactory) | Custom persistence backend (experimental) |
WithCustomVisibilityStoreFactory(VisibilityStoreFactory) | Custom visibility backend |
WithCustomHistoryArchiverFactory(...) | Custom history archiver |
WithCustomVisibilityArchiverFactory(...) | Custom visibility archiver |
WithClientFactoryProvider(client.FactoryProvider) | Custom inter-service client factory |
WithSearchAttributesMapper(searchattribute.Mapper) | Search attribute alias mapping |
WithChainedFrontendGrpcInterceptors(...grpc.UnaryServerInterceptor) | Append custom interceptors |
WithCustomMetricsHandler(metrics.Handler) | Custom metrics sink |
WithElasticsearchHttpClient(*http.Client) | Custom ES HTTP client |
WithPersistenceServiceResolver(resolver.ServiceResolver) | Address resolution for DB services |
Backward compatibility: No explicit versioning strategy in code, but the ServerOption interface is designed for stability — new options are added as new functions, old code continues to work.
Plugin / Extension System#
Temporal’s extensibility is interface-based, surfaced through the ServerOption embedding API:
| Extension Point | Interface | Purpose |
|---|---|---|
| Authorization | authorization.Authorizer | Allow/deny per RPC |
| Claim mapping | authorization.ClaimMapper | JWT claim extraction |
| Persistence | persistenceclient.AbstractDataStoreFactory | Custom storage backend |
| Visibility | visibility.VisibilityStoreFactory | Custom search/visibility backend |
| History archival | provider.CustomHistoryArchiverFactory | Custom history archive destination |
| Visibility archival | provider.CustomVisibilityArchiverFactory | Custom visibility archive destination |
| Metrics | metrics.Handler | Custom metrics sink (Prometheus, Datadog, etc.) |
| gRPC interceptors | grpc.UnaryServerInterceptor | Custom middleware in the Frontend chain |
| Dynamic config | dynamicconfig.Client | Custom feature flag / config backend |
| Search attributes | searchattribute.Mapper | Alias ↔ field name translation |
The CHASM subsystem adds a second extension point for new execution model components. chasm.Library implementors (RegisterServices(*grpc.Server)) can contribute new state machine types and gRPC services to the cluster.
Key observations#
Three-tier API architecture: Public client APIs (WorkflowService/OperatorService in external module) → Internal inter-service APIs (HistoryService/MatchingService in this repo) → Admin APIs (AdminService). The external module boundary enforces API stability — the server implements a stable interface it does not own.
REST is a thin transcoding layer: The HTTP API is not a separately maintained REST API; it is mechanically derived from the gRPC proto annotations via grpc-gateway. The inline client connection design means REST requests traverse the full gRPC interceptor chain without a network hop, giving REST and gRPC identical middleware behavior.
Nexus HTTP is a first-class protocol: The Nexus HTTP handler is not a REST wrapper over workflow APIs; it is a separate protocol (the CNCF Nexus spec) for composable async operations. It coexists on the same HTTP port as the REST gateway but has dedicated routing.
The
temporalembedding package is a well-designed escape hatch: The functional options API makes it easy to replace any subsystem (persistence, auth, metrics, archival) for testing or custom deployments, without forking the server. This is heavily used bytemporalio/temporal-go-testsand testing frameworks.~60 public RPCs, ~130 total RPCs across services: The API surface is large but well-organized — public vs. internal vs. admin separation makes the blast radius of any change clear.
API categories via proto options: All RPCs carry an
api_categoryoption (API_CATEGORY_STANDARD,API_CATEGORY_LONG_POLL,API_CATEGORY_SYSTEM). This is used for rate limiting — long-poll RPCs and system RPCs get different quota budgets, preventing polling traffic from starving user-initiated calls.