temporalio/temporal
Frontend service
Active contributors: alex, david, yux
Purpose
Frontend is the cluster's public API gateway. It terminates gRPC and HTTP from SDKs, the CLI, and the Web UI; runs authentication, authorization, namespace lookup, and rate-limiting; and routes requests to History, Matching, or Worker. It is stateless — every Frontend instance handles every namespace.
Directory layout
service/frontend/
├── service.go # Service struct, gRPC server bootstrap
├── fx.go # fx wiring (long; defines all DI providers)
├── workflow_handler.go # Public WorkflowService gRPC handlers (~260KB)
├── operator_handler.go # OperatorService gRPC handlers (cluster admin)
├── admin_handler.go # AdminService gRPC handlers (in-cluster ops)
├── namespace_handler.go # Namespace CRUD and lookup
├── nexus_handler.go # Nexus inbound gRPC
├── nexus_completion_http_handler.go
├── nexus_operation_http_handler.go
├── http_api_server.go # HTTP/REST gateway built on grpc-gateway
├── openapi_http_handler.go # /api/v1/openapi.json
├── health_check.go # gRPC health checks
├── version_checker.go # SDK version reporting
├── task_reachability.go # API helpers for task-queue versioning
├── interface.go # Internal interfaces (handler, etc.)
├── overrides.go # Per-namespace dynamic-config overrides
├── errors.go # Frontend-specific service errors
├── experiments.go # Feature-flag wiring
├── protojson_marshaler.go # JSON marshaling tweaks for HTTP API
├── validators.go # Per-API request validation helpers
└── configs/ # Default ratelimit/retry policiesKey abstractions
| Type / file | What it is |
|---|---|
WorkflowHandler (service/frontend/workflow_handler.go) |
Implements temporal.api.workflowservice.v1.WorkflowService — every public RPC. |
OperatorHandlerImpl (service/frontend/operator_handler.go) |
Implements OperatorService — namespace, search-attribute, cluster admin. |
AdminHandler (service/frontend/admin_handler.go) |
Implements AdminService — internal cluster operations (replication, shard mgmt). |
NamespaceHandlerImpl (service/frontend/namespace_handler.go) |
Namespace CRUD; consumed by both WorkflowHandler and OperatorHandler. |
NexusHTTPHandler (service/frontend/nexus_handler.go) |
Nexus inbound HTTP/gRPC handlers. |
HTTPAPIServer (service/frontend/http_api_server.go) |
grpc-gateway translator from REST to gRPC. |
How it works
sequenceDiagram
participant Client as SDK / CLI / UI
participant Auth as Authorizer
participant Limit as Rate Limiters
participant Handler as WorkflowHandler
participant Backend as History / Matching
Client->>Handler: gRPC StartWorkflowExecution
Handler->>Auth: claims + namespace
Auth-->>Handler: allow / deny
Handler->>Limit: namespace + global QPS
Limit-->>Handler: ok / ResourceExhausted
Handler->>Handler: validate + map to internal proto
Handler->>Backend: client.HistoryClient.StartWorkflowExecution
Backend-->>Handler: history response
Handler-->>Client: public responseA request lands at the gRPC server defined in service/frontend/service.go, passes through interceptors generated from cmd/tools/genrpcserverinterceptors/, and arrives at one of the handler methods. The handler:
- Authorizes. Pluggable via
common/authorization/. The defaultnoopAuthorizerallows everything; production deployments inject a JWT-based one. - Looks up the namespace in the cache provided by
common/namespace/. - Rate-limits via
common/quotas/. Multiple limiters (global, namespace, namespace-replication-task) combine. - Routes to the correct backend service via
client.HistoryClientorclient.MatchingClient. The History client is shard-aware: it picks the right host from the membership ring. - Returns translating internal errors into typed
serviceerror.*for the SDK.
The HTTP API mirrors the gRPC API one-to-one. HTTPAPIServer registers routes from the OpenAPI/Swagger spec generated alongside the public protos and forwards each one to the corresponding gRPC handler over loopback. Nexus has its own dedicated HTTP path because its semantics (callbacks, headers) are not naturally REST.
Integration points
- Inbound: SDK clients via gRPC (port 7233), Web UI / CLI via HTTP (7243), Nexus inbound (configurable).
- Outbound: History (
client.HistoryClient), Matching (client.MatchingClient), Admin (client.AdminClient), and other clusters (client.RemoteAdminClient) for replication. - Caches:
- Namespace cache (
common/namespace/registry.go) — refreshed via long-poll againstListNamespaces. - Cluster metadata cache (
common/cluster/metadata.go) — fed bycluster_metadatatable. - Search-attribute mapper (
common/searchattribute/) — maps user-defined names to indexed fields.
- Namespace cache (
- Metrics: every handler emits standard latency / count / error metrics with the API name as a tag — definitions in
common/metrics/metric_defs.go.
Internal Frontend variant
The internal-frontend service is the same handler set but bound to a separate listener that the cluster's other services use. It bypasses public auth and is intended for in-cluster traffic only. Provided so operators can route SDK traffic via a public Frontend and cross-service traffic via the internal one. Wired up in temporal/fx.go and toggled by config.
Entry points for modification
- Adding a public RPC: modify the proto in
temporalio/api, regenerate stubs, then add the handler inworkflow_handler.go. For server-internal admin RPCs, editproto/internal/temporal/server/api/adminservice/v1/and regen withmake proto. - Adding HTTP-only behaviour:
http_api_server.gois the entry; for one-off REST endpoints (Nexus completion etc.) see the dedicatednexus_*files. - Adding rate-limit semantics:
configs/holds default policies; the dynamic-config keys are incommon/dynamicconfig/constants.go. - Tweaking a per-namespace policy:
overrides.golayers per-namespace dynamic-config overrides on top of the global defaults.
Related pages
- API reference — proto definitions and HTTP routes.
- Security — authorization and TLS.
- Namespaces — multi-tenant boundaries.
- Matching — where polls land after Frontend.
- History — where state-modifying RPCs land.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.