Deploy a Serverless Worker on GCP Cloud Run
This guide walks through deploying a Temporal Serverless Worker on a GCP Cloud Run worker pool. You deploy your Worker container to a worker pool scaled to zero instances, then create a Worker Deployment Version whose compute provider points at that worker pool. When a Task arrives with no active pollers, Temporal scales the worker pool up to process the Task and scales it back to zero when the invocation window ends.
Prerequisites
- A Temporal Cloud account with a GCP-hosted Namespace, or a self-hosted Temporal Service v1.31.0 or later. The Namespace's cloud provider must match the serverless compute provider.
- Every Workflow must declare a versioning behavior, or the Worker must set a default versioning behavior.
- A GCP project with the Cloud Run API enabled and permission to create Cloud Run worker pools, Secret Manager secrets, and service accounts.
- A service account that Temporal uses to invoke the worker pool. Grant it permission to run the worker pool and to read the TLS secrets it mounts.
- The
gcloudCLI installed and authenticated, andyqfor converting the worker pool manifest to JSON. You can also perform these steps with the GCP Console. - The Temporal CLI v1.8.0 or later, which adds the GCP Cloud Run compute provider flags used below.
- If your Namespace uses mTLS, the client certificate and private key you use to connect. Save them to local files (for
example,
client.pemandclient.key). You reference these for both the Worker and the CLI.
1. Configure CLI access to your Namespace
The commands in this guide connect to your Namespace with mTLS. Store the connection details in a CLI configuration profile so you don't repeat them on every command:
temporal config --profile serverless set --prop address \
--value "<your-namespace>.<account>.tmprl.cloud:7233"
temporal config --profile serverless set --prop namespace \
--value "<your-namespace>"
temporal config --profile serverless set --prop tls --value true
temporal config --profile serverless set --prop tls.client_cert_path \
--value "/path/to/client.pem"
temporal config --profile serverless set --prop tls.client_key_path \
--value "/path/to/client.key"
This writes the following profile to your Temporal CLI configuration file, which you can also edit directly:
[profile.serverless]
address = "<your-namespace>.<account>.tmprl.cloud:7233"
namespace = "<your-namespace>"
[profile.serverless.tls]
client_cert_path = "/path/to/client.pem"
client_key_path = "/path/to/client.key"
Verify the connection before continuing. Both commands should exit without an error:
temporal config get --profile serverless
temporal workflow list --profile serverless --limit 1
2. Deploy the Worker to a Cloud Run worker pool
Package your Worker as a container image, store its TLS credentials in Secret Manager, and deploy it to a Cloud Run worker pool scaled to zero instances.
i. Build the Worker container image
Build a container image that runs a Temporal Worker and push it to a registry Cloud Run can pull from, such as Artifact Registry. The Worker must:
- Connect to your Namespace address with mTLS, using the certificate and key mounted into the container.
- Register with the Worker Deployment name and Build ID you use in the steps below.
- Set a versioning behavior for every Workflow, or set a default versioning
behavior of
PinnedorAutoUpgrade.
For guidance on writing a Worker and setting these options, see the SDK Worker documentation for Go, Python, or TypeScript.
ii. Store the TLS credentials in Secret Manager
Create Secret Manager secrets for the client certificate and key. The worker pool manifest mounts these into the container:
gcloud secrets create worker-tls-cert --data-file=client.pem
gcloud secrets create worker-tls-key --data-file=client.key
Grant the invocation service account permission to read both secrets:
gcloud secrets add-iam-policy-binding worker-tls-cert \
--member="serviceAccount:<your-invocation-service-account>@<your-gcp-project>.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
gcloud secrets add-iam-policy-binding worker-tls-key \
--member="serviceAccount:<your-invocation-service-account>@<your-gcp-project>.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
iii. Create and configure the worker pool
Create the worker pool in the GCP Console under Cloud Run > Worker Pools > Deploy worker pool, or apply the
manifest below. Set the manual instance count to 0. Temporal scales the pool up when Tasks arrive and back to zero when
the invocation window ends.
Save the following manifest as worker-pool.yaml and replace the values marked with # change-me:
metadata.name— the worker pool name.metadata.namespace— your GCP project number.image— your Worker container image.serviceAccountName— the invocation service account.- The Worker's connection arguments and its Worker Deployment name, Build ID, and versioning behavior. The exact arguments depend on your image. The example below passes them as container arguments.
apiVersion: run.googleapis.com/v1
kind: WorkerPool
metadata:
annotations:
run.googleapis.com/manualInstanceCount: '0'
run.googleapis.com/scalingMode: manual
labels:
cloud.googleapis.com/location: us-central1
name: <your-worker-pool-name> # change-me
namespace: '<your-gcp-project-number>' # change-me
spec:
instanceSplits:
- latestRevision: true
percent: 100
template:
metadata:
annotations:
run.googleapis.com/execution-environment: gen2
spec:
containerConcurrency: 0
serviceAccountName: <your-invocation-service-account>@<your-gcp-project>.iam.gserviceaccount.com # change-me
containers:
- image: <your-worker-image> # change-me
name: worker-1
args:
- --server-address=<your-namespace>.<account>.tmprl.cloud:7233
- --namespace=<your-namespace>
- --tls
- --tls-cert-path=/etc/tls/cert/worker-tls-cert
- --tls-key-path=/etc/tls/key/worker-tls-key
- --default-versioning-behavior=pinned
- --deployment-name=<your-worker-deployment-name> # change-me
- --deployment-build-id=1.0
resources:
limits:
cpu: '2'
memory: 512Mi
volumeMounts:
- mountPath: /etc/tls/cert
name: secret-cert
- mountPath: /etc/tls/key
name: secret-key
volumes:
- name: secret-cert
secret:
secretName: worker-tls-cert
items:
- key: latest
path: worker-tls-cert
- name: secret-key
secret:
secretName: worker-tls-key
items:
- key: latest
path: worker-tls-key
Convert the manifest to JSON and apply it as a revision of the worker pool through the Cloud Run Admin API:
POOL=<your-worker-pool-name> # must match metadata.name
yq -o=json worker-pool.yaml > "$POOL.json"
curl -s -X PUT \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://us-central1-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/<your-gcp-project>/workerpools/$POOL" \
-d @"$POOL.json"
iv. Verify the worker pool
Confirm the worker pool exists and its configuration matches the manifest:
gcloud run worker-pools describe <your-worker-pool-name> --region us-central1 --format export
3. Create the Worker Deployment
Create the Worker Deployment that the version attaches to. The name must match the deployment name your Worker registers with in Step 2.
temporal worker deployment create \
--profile serverless \
--name <your-worker-deployment-name>
4. Create a Worker Deployment Version
Create a Worker Deployment Version with a compute provider that points at your Cloud Run worker pool. The compute configuration tells Temporal how to invoke your Worker: the GCP project, region, worker pool, and the service account to run as. The deployment name and Build ID must match the values your Worker registers with.
You can create the version using the Temporal UI or the Temporal CLI.
- Temporal UI
- Temporal CLI
- In the Temporal UI, open your Namespace.
- In the left pane, select Workers.
- Click Create Worker Deployment in the upper right corner.
- Under Configuration, enter a Name and Build ID. These must match the deployment name and Build ID your Worker registers with.
- Under Compute, select GCP Cloud Run and provide the project, region, worker pool, and invocation service account.
- Click Save.
When you create a version through the UI, the version is automatically set as current. Skip to Verify the deployment.
Use the CLI for manual setup, shell scripts, and CI/CD pipelines. When you create a version through the CLI, you must set the version as current as a separate step.
temporal worker deployment create-version \
--profile serverless \
--deployment-name <your-worker-deployment-name> \
--build-id 1.0 \
--gcp-cloud-run-project <your-gcp-project> \
--gcp-cloud-run-region us-central1 \
--gcp-cloud-run-worker-pool <your-worker-pool-name> \
--gcp-cloud-run-service-account <your-invocation-service-account>@<your-gcp-project>.iam.gserviceaccount.com
| Flag | Description |
|---|---|
--deployment-name | Worker Deployment name. Must match the deployment name your Worker registers with. |
--build-id | Worker Deployment Version Build ID. Must match the Build ID your Worker registers with. |
--gcp-cloud-run-project | GCP project that contains the worker pool. |
--gcp-cloud-run-region | Region of the worker pool (for example, us-central1). |
--gcp-cloud-run-worker-pool | Name of the Cloud Run worker pool Temporal invokes for this version. |
--gcp-cloud-run-service-account | Service account Temporal uses to run the worker pool. |
5. Set version as current
If you created the version through the Temporal UI, the version is already current and you can skip this step.
If you used the CLI, set the version as current. Without this step, Tasks on the Task Queue don't route to the version, and Temporal doesn't invoke the worker pool.
temporal worker deployment set-current-version \
--profile serverless \
--deployment-name <your-worker-deployment-name> \
--build-id 1.0
6. Verify deployment
Start a Workflow on the same Task Queue to confirm that Temporal invokes your Cloud Run Worker.
temporal workflow start \
--profile serverless \
--task-queue <your-task-queue> \
--type MyWorkflow \
--input '"Hello, serverless!"'
When the Task lands on the Task Queue with no active pollers, Temporal detects the compute provider configuration and scales the worker pool up. The Worker starts, connects to Temporal, picks up the Task, and processes it.
Verify the invocation by checking:
- Temporal UI: Open the Workflows view for your Namespace. The Workflow Execution should show Task completions in its Event History.
- GCP Console: Open Cloud Run worker pools. Your worker pool should show instance, CPU, and memory metrics for the invocation.
If the Workflow does not progress or the worker pool is not invoked, see Troubleshoot Serverless Workers.