Deploy a serverless Worker on AWS Lambda
This guide walks through deploying a Temporal Worker on AWS Lambda.
Prerequisites
- A Temporal Service vx.xx.x or later.
- An AWS account with permissions to create and invoke Lambda functions and create IAM roles.
- The
awsCLI installed and configured with your AWS credentials. - Your Temporal Service frontend must be reachable from the Lambda execution environment. For Temporal Cloud, no additional configuration is needed. For self-hosted deployments on a private network, configure the Lambda function with VPC access to reach the Temporal frontend.
- The Go SDK (
go.temporal.io/sdk)
Write the Worker code
Write a Worker that runs inside a Lambda function. The Worker handles the per-invocation lifecycle: connecting to Temporal, polling for tasks, and gracefully shutting down before the Lambda deadline.
Use the Go SDK's lambdaworker package.
package main
import (
lambdaworker "go.temporal.io/sdk/contrib/aws/lambdaworker"
"go.temporal.io/sdk/worker"
"go.temporal.io/sdk/workflow"
)
func main() {
lambdaworker.RunWorker(worker.WorkerDeploymentVersion{
DeploymentName: "my-app",
BuildID: "build-1",
}, func(opts *lambdaworker.Options) error {
opts.TaskQueue = "my-task-queue"
opts.RegisterWorkflowWithOptions(MyWorkflow, workflow.RegisterOptions{
VersioningBehavior: workflow.VersioningBehaviorAutoUpgrade,
})
opts.RegisterActivity(MyActivity)
return nil
})
}
Each Workflow must declare a versioning behavior at registration time, either AutoUpgrade or Pinned.
For details on configuration options, Lambda-tuned defaults, and the invocation lifecycle, see Serverless Workers - Go SDK.
Deploy the Lambda function
Create the Lambda execution role
Every Lambda function needs an execution role that grants it permission to run.
This is the standard IAM role with lambda.amazonaws.com as the trusted principal.
aws iam create-role \
--role-name my-temporal-worker-execution \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "lambda.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}'
aws iam attach-role-policy \
--role-name my-temporal-worker-execution \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Grant the execution role whatever additional permissions your Workflow and Activity code needs (S3, DynamoDB, etc.). This role is separate from the IAM role that Temporal uses to invoke the function.
Build and package
Cross-compile for Lambda's Linux runtime:
GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o bootstrap ./worker
Create a temporal.toml file with your Temporal Service connection details.
The lambdaworker package reads this file at startup to connect to the Temporal Service.
[profile.default]
address = "<your-temporal-address>:7233"
namespace = "<your-namespace>"
If your Temporal Service requires mTLS authentication, add the TLS configuration:
[profile.default]
address = "<your-namespace>.<account>.tmprl.cloud:7233"
namespace = "<your-namespace>.<account>"
[profile.default.tls]
client_cert_path = "client.pem"
client_key_path = "client.key"
Package the binary, config file, and any credentials into a zip file:
zip function.zip bootstrap temporal.toml
If using mTLS, include the certificate files:
zip function.zip bootstrap client.pem client.key temporal.toml
Create the Lambda function
aws lambda create-function \
--function-name my-temporal-worker \
--runtime provided.al2023 \
--handler bootstrap \
--architectures x86_64 \
--role arn:aws:iam::<YOUR_ACCOUNT_ID>:role/my-temporal-worker-execution \
--zip-file fileb://function.zip \
--timeout 60 \
--memory-size 256
To update an existing function with new code:
aws lambda update-function-code \
--function-name my-temporal-worker \
--zip-file fileb://function.zip
In production, store credentials in a secret store rather than bundling them with the deployment package. Encrypt sensitive values using AWS KMS.
Configure IAM for Temporal invocation
Temporal needs permission to invoke your Lambda function.
The Temporal server assumes an IAM role in your AWS account to call lambda:InvokeFunction.
The trust policy on the role includes an External ID condition to prevent confused deputy attacks.
Deploy the following CloudFormation template to create the invocation role and its permissions.
| Parameter | Description |
|---|---|
TemporalPrincipalArn | The IAM principal that the Temporal server runs as. For Temporal Cloud, this is provided in your Namespace configuration. For self-hosted, this is the IAM identity of the server process (IAM user, EC2 instance role, EKS service account, etc.). |
ExternalId | A unique identifier that Temporal presents when assuming the role. For Temporal Cloud, this is provided in your Namespace configuration. For self-hosted, this is the value you configure in the compute provider settings. |
LambdaFunctionArn | The ARN of the Lambda function that Temporal will invoke. |
# CloudFormation template coming soon
Create a Worker Deployment Version
Create a Worker Deployment Version with a compute provider that points to your Lambda function.
The compute configuration tells Temporal how to invoke your Worker: the provider type (aws-lambda), the Lambda function ARN, and the IAM role to assume.
The deployment name and build ID must match the values in your Worker code.
You can create the version using the Temporal UI, the Temporal CLI, or programmatically with an SDK.
Temporal UI
Use the UI for one-off setup and exploration.
When you create a version through the UI, the version is automatically set as current.
Temporal CLI
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 \
--namespace <YOUR_NAMESPACE> \
--deployment-name my-app \
--build-id build-1 \
--aws-lambda-invoke arn:aws:lambda:<REGION>:<ACCOUNT_ID>:function:my-temporal-worker \
--scaler-min-instances 0 \
--scaler-max-instances 5
SDK
Use the SDK when the deployment registration is part of your application, for example a setup program that provisions infrastructure and registers the version together, or when you need to compute values dynamically. When you create a version through the SDK, you must set the version as current as a separate step.
// Create the worker deployment
client.CreateWorkerDeployment(ctx, &workflowservice.CreateWorkerDeploymentRequest{
Namespace: "default",
DeploymentName: "my-app",
})
// Create a version with Lambda compute config
client.CreateWorkerDeploymentVersion(ctx, &workflowservice.CreateWorkerDeploymentVersionRequest{
Namespace: "default",
DeploymentVersion: &deploymentpb.WorkerDeploymentVersion{
DeploymentName: "my-app",
BuildId: "build-1",
},
ComputeConfig: &computepb.ComputeConfig{
ScalingGroups: map[string]*computepb.ComputeConfigScalingGroup{
"default": {
Provider: &computepb.ComputeProvider{
Type: "aws-lambda",
Details: /* Lambda ARN, role ARN, external ID */,
},
},
},
},
})
Set the 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 or SDK, set the version as current. Without this step, tasks on the Task Queue will not route to the version, and Temporal will not invoke the Lambda function.
temporal worker deployment set-current-version \
--deployment-name my-app \
--build-id build-1 \
--ignore-missing-task-queues
The --ignore-missing-task-queues flag is needed because no Worker has polled the Task Queue yet.
With serverless Workers, the Worker only connects when Temporal invokes the Lambda function.
Verify the deployment
Start a Workflow on the same Task Queue to confirm that Temporal invokes your Lambda Worker.
temporal workflow start \
--task-queue my-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 invokes your Lambda function. The Worker starts, connects to Temporal, picks up the task, and processes it.
You can verify the invocation by checking:
- Temporal UI: The Workflow execution should show task completions in the event history.
- AWS CloudWatch Logs: The Lambda function's log group (
/aws/lambda/my-temporal-worker) should show invocation logs with the Worker startup, task processing, and graceful shutdown.