Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/temporal-sa/temporal-cloud-proxy/llms.txt

Use this file to discover all available pages before exploring further.

Temporal Cloud Proxy exposes a single plain-text gRPC WorkflowService endpoint (default port 7233) and acts as a transparent multiplexer in front of one or more Temporal Cloud namespaces. At startup the proxy reads its YAML configuration and builds a connection map — one entry per configured workload — where each entry holds a dedicated TLS gRPC client connection to Temporal Cloud, an optional worker authenticator, and an optional payload encryption codec. Inbound worker calls are looked up in this map by the workload-id gRPC metadata header, subjected to any configured authentication and encryption steps, and then forwarded to the matching Temporal Cloud namespace. Workers need no knowledge of namespace credentials, KMS keys, or SPIRE — the proxy is the single point of enforcement for all of it.

Request Lifecycle

The following sequence describes the path of every gRPC call through the proxy, from the moment a worker opens a connection to the moment the response is returned.
1

Worker connects on port 7233 (plain gRPC)

The proxy’s gRPC server accepts connections without TLS. Workers connect to <proxy-host>:7233 using a standard Temporal SDK client pointed at the proxy address. No client certificate, no TLS configuration, and no Temporal Cloud credentials are required on the worker side.
2

Worker attaches the workload-id metadata header

On each gRPC call, the worker includes a workload-id key in the gRPC request metadata. This header is the primary routing signal — it must carry exactly one value matching a workload_id defined in the proxy configuration. If the header is absent or contains multiple values, the proxy returns codes.InvalidArgument immediately.
3

Proxy resolves the namespace connection

The proxy reads the workload-id value and performs a read-locked lookup in the connectionMux map (a map[string]namespaceConnection). If no entry exists for the given ID, the proxy logs a warning and returns codes.InvalidArgument. If found, the call proceeds using the resolved namespaceConnection, which carries a pre-established grpc.ClientConn to the target Temporal Cloud namespace.
4

Worker authentication is enforced (if configured)

When the resolved workload has an authentication block in its configuration, the proxy checks for an authorization header in the incoming metadata. If the header is missing or appears more than once, the proxy returns codes.InvalidArgument. The token is then passed to the workload’s Authenticator implementation (JWT or SPIFFE). If the authenticator itself returns an error (e.g. a JWKS fetch failure), the proxy returns codes.Unknown. If the authenticator succeeds but reports the token as invalid, the proxy returns codes.Unauthenticated. A successful, valid authentication allows the call to continue.
5

Payload codec intercepts the call (if encryption is configured)

When the workload has an encryption block, a converter.PayloadCodecGRPCClientInterceptor is chained onto the outbound gRPC client for that workload. This interceptor encodes (encrypts) outgoing payloads before they leave the proxy toward Temporal Cloud, and decodes (decrypts) incoming payloads in responses before they are returned to the worker. The worker always sees plaintext payloads; ciphertext never leaves the proxy boundary.
6

Call is forwarded to Temporal Cloud over TLS

The proxy calls Invoke on the workload’s grpc.ClientConn, which is already configured with the appropriate TLS transport credentials and, if API key auth is used, an outbound metadata interceptor that injects the authorization: Bearer <key> and temporal-namespace headers. The Temporal Cloud response travels back through the same chain in reverse and is returned to the worker.

Workload Routing

The central data structure is connectionMux, a map[string]namespaceConnection keyed by workload_id. It is populated once during proxy startup by iterating over the workloads list in the YAML configuration. Each namespaceConnection holds:
  • A *grpc.ClientConn pre-dialled to the workload’s host_port with TLS credentials
  • A pointer to an Authenticator (nil when no worker auth is configured)
  • A MetricsHandler scoped to the workload’s workload_id and namespace attributes
All runtime reads of connectionMux are protected by a sync.RWMutex, making concurrent worker calls safe. The map is never modified after startup — a configuration change requires a proxy restart. If you configure two workloads with the same workload_id, the proxy refuses to start and reports a validation error.

Namespace Authentication

Each workload configures exactly one method for authenticating to Temporal Cloud. The two supported methods are mutually exclusive — setting both on a single workload is a validation error. mTLS The proxy loads a PEM-encoded client certificate and private key from the paths specified in tls.cert_file and tls.key_file. These are added to a *tls.Config and passed as credentials.NewTLS(tlsConfig) to the grpc.NewClient dial options. The TLS handshake with Temporal Cloud then uses this certificate automatically on every call.
temporal_cloud:
  authentication:
    tls:
      cert_file: "/certs/client.crt"
      key_file: "/certs/client.key"
API Key The API key is resolved at startup — either from a literal value field or by reading the environment variable named in the env field. The proxy installs a grpc.UnaryClientInterceptor on the outbound connection that, for every call, copies the incoming metadata, strips any existing authorization and temporal-namespace entries, and appends the correct values before forwarding:
authorization: Bearer <api-key>
temporal-namespace: <namespace>
This ensures that worker-supplied authorization headers do not leak through to Temporal Cloud and that the correct namespace is always declared regardless of what the worker sends.
temporal_cloud:
  authentication:
    api_key:
      env: TEMPORAL_API_KEY   # or use: value: "your-key"

Worker Authentication

Worker authentication is optional per workload. When configured, the proxy validates every inbound call’s authorization header before routing it. Two authenticator types are supported. JWT The JwtAuthenticator fetches the workload’s JWKS endpoint at startup and refreshes it every five minutes. On each call it:
  1. Strips the Bearer prefix from the authorization header value.
  2. Parses and cryptographically verifies the JWT signature against the JWKS keys.
  3. Checks that at least one aud claim value matches the configured audiences list.
  4. Verifies that the token has not expired (exp claim).
If any check fails, the authenticator returns an error, which the proxy surfaces as codes.Unknown (“failed to authenticate”). If parsing succeeds but the token is deemed invalid, the proxy returns codes.Unauthenticated (“invalid token”).
authentication:
  type: "jwt"
  config:
    jwks-url: "https://auth.example.com/.well-known/keys"
    audiences:
      - "temporal_cloud_proxy"
SPIFFE / SPIRE The SpiffeAuthenticator connects to a local SPIRE agent over a Unix domain socket at Init time and creates a workloadapi.JWTSource. On each call it:
  1. Strips the Bearer prefix from the authorization header value.
  2. Calls jwtsvid.ParseAndValidate to verify the JWT-SVID signature and audience against the JWTSource.
  3. Checks whether the validated SVID’s SPIFFE ID appears in the configured spiffe_ids allowlist.
If the SPIFFE ID is not in the allowlist, authentication fails even if the token signature is valid.
authentication:
  type: "spiffe"
  config:
    spiffe_ids:
      - "spiffe://example.org/my-workload"
    endpoint: "unix:///tmp/spire-agent/public/api.sock"
    audiences:
      - "temporal_cloud_proxy"

Payload Encryption

When a workload’s encryption block is present, the proxy wraps the outbound gRPC connection with Temporal’s PayloadCodecGRPCClientInterceptor. The codec implementation uses AES-GCM envelope encryption:
  1. Encrypt (Encode): A new data key is generated and encrypted (wrapped) by the configured KMS key. The plaintext payload bytes are encrypted with AES-GCM using this data key. The resulting Payload carries three metadata fields:
    Metadata keyValue
    encodingbinary/encrypted
    encryption-key-idKMS key identifier
    encrypted-data-keyKMS-wrapped ciphertext of the data key
  2. Decrypt (Decode): On the return path, the codec reads encryption-key-id and encrypted-data-key from payload metadata, asks KMS to unwrap the data key, and uses it to decrypt the AES-GCM ciphertext. Payloads whose encoding metadata is not binary/encrypted are passed through unchanged.
Caching A CachingMaterialsManager wraps the raw KMS provider to avoid a KMS API call on every payload. Keys are cached subject to three configurable bounds — whichever limit is reached first causes the key to be evicted:
encryption:
  caching:
    max_cache: 100    # maximum number of cached keys
    max_age: "10m"    # maximum age of a cached key
    max_usage: 100    # maximum number of times a cached key may be used
If no caching configuration is provided, the defaults are 100 keys, 5 minutes age, and 100 usages. AWS KMS
encryption:
  type: "aws-kms"
  config:
    key-id: "arn:aws:kms:us-east-1:123456789012:key/mrk-abc123"
GCP KMS
encryption:
  type: "gcp-kms"
  config:
    key-name: "projects/my-project/locations/global/keyRings/my-ring/cryptoKeys/my-key"

gRPC Headers Reference

The following gRPC metadata headers are read by the proxy on every inbound call.
HeaderRequiredDescription
workload-idAlwaysSelects which workload configuration to use for routing, authentication, and encryption. Must match exactly one workload_id in the proxy configuration. Exactly one value is permitted.
authorizationWhen worker auth is configuredBearer token used for worker identity validation. For JWT workloads this is a signed JWT; for SPIFFE workloads this is a JWT-SVID issued by SPIRE. Exactly one value is permitted.
Workers do not need TLS certificates to connect to the proxy. The proxy listens on a plain-text gRPC port — all TLS toward Temporal Cloud is handled internally using the credentials you configure per workload. This means you can run workers in environments that have no access to namespace certificates at all.

Build docs developers (and LLMs) love