Open-Source Wikis

/

Temporal

/

Services

/

Frontend service

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 policies

Key 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 response

A 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:

  1. Authorizes. Pluggable via common/authorization/. The default noopAuthorizer allows everything; production deployments inject a JWT-based one.
  2. Looks up the namespace in the cache provided by common/namespace/.
  3. Rate-limits via common/quotas/. Multiple limiters (global, namespace, namespace-replication-task) combine.
  4. Routes to the correct backend service via client.HistoryClient or client.MatchingClient. The History client is shard-aware: it picks the right host from the membership ring.
  5. 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 against ListNamespaces.
    • Cluster metadata cache (common/cluster/metadata.go) — fed by cluster_metadata table.
    • Search-attribute mapper (common/searchattribute/) — maps user-defined names to indexed fields.
  • 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

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Frontend service – Temporal wiki | Factory