Skip to main content

Serverless Workers on AWS Lambda - Go SDK

The lambdaworker package lets you run a Temporal Serverless Worker on AWS Lambda. Deploy your Worker code as a Lambda function, and Temporal Cloud invokes it when Tasks arrive. Each invocation starts a Worker, polls for Tasks until the Lambda deadline approaches, then gracefully drains and shuts down. You register Workflows and Activities the same way you would with a standard Worker.

For a full end-to-end deployment guide covering AWS IAM setup, compute configuration, and verification, see Deploy a Serverless Worker.

Create and run a Worker in Lambda

Use the RunWorker function to start a Lambda-based Worker. Pass a WorkerDeploymentVersion and a callback that registers your Workflows and Activities.

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
})
}

The WorkerDeploymentVersion is required. Worker Deployment Versioning is always enabled for Serverless Workers. Each Workflow must declare a versioning behavior at registration time, either AutoUpgrade or Pinned.

The Options callback gives you access to the same registration methods you use with a traditional Worker: RegisterWorkflow, RegisterWorkflowWithOptions, RegisterActivity, RegisterActivityWithOptions, and RegisterNexusService.

Configure the Temporal connection

The lambdaworker package automatically loads Temporal client configuration from a TOML config file and environment variables. Refer to Environment Configuration for more details.

Encrypt sensitive values like TLS keys or API keys. Refer to AWS documentation for options.

Adjust Worker defaults for Lambda

The lambdaworker package applies conservative defaults suited to short-lived Lambda invocations. These differ from standard Worker defaults to avoid overcommitting resources in a constrained environment. Except for ShutdownDeadlineBuffer, these are the same worker.Options available to any Temporal Worker, just with lower values for Lambda's constrained environment.

SettingLambda default
MaxConcurrentActivityExecutionSize2
MaxConcurrentWorkflowTaskExecutionSize10
MaxConcurrentLocalActivityExecutionSize2
MaxConcurrentNexusTaskExecutionSize5
MaxConcurrentActivityTaskPollers1
MaxConcurrentWorkflowTaskPollers2
MaxConcurrentNexusTaskPollers1
WorkerStopTimeout5 seconds
DisableEagerActivitiesAlways true
Sticky cache size100
ShutdownDeadlineBuffer7 seconds

DisableEagerActivities is always true and cannot be overridden. Eager Activities require a persistent connection, which Lambda invocations don't maintain.

ShutdownDeadlineBuffer is specific to the lambdaworker package. It controls how much time before the Lambda deadline the Worker begins its graceful shutdown. The default is WorkerStopTimeout + 2 seconds.

Add observability with OpenTelemetry

The lambdaworker/otel sub-package provides OpenTelemetry integration with defaults configured for the AWS Distro for OpenTelemetry (ADOT) Lambda layer. With this enabled, the Worker emits SDK metrics and distributed traces for Workflow and Activity executions. The ADOT Lambda layer collects this telemetry and can forward traces to AWS X-Ray and metrics to Amazon CloudWatch.

The underlying metrics and traces are the same ones the Go SDK emits in any environment. For general observability concepts and the full list of available metrics, see Observability - Go SDK and the SDK metrics reference.

import (
lambdaworker "go.temporal.io/sdk/contrib/aws/lambdaworker"
otel "go.temporal.io/sdk/contrib/aws/lambdaworker/otel"
"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"

if err := otel.ApplyDefaults(opts, &opts.ClientOptions, otel.Options{}); err != nil {
return err
}

opts.RegisterWorkflowWithOptions(MyWorkflow, workflow.RegisterOptions{
VersioningBehavior: workflow.VersioningBehaviorAutoUpgrade,
})
opts.RegisterActivity(MyActivity)

return nil
})
}

ApplyDefaults configures both metrics and tracing. By default, telemetry is sent to localhost:4317, which is the ADOT Lambda layer's default collector endpoint.

If you only need metrics or tracing, use otel.ApplyMetrics or otel.ApplyTracing individually.