Your first Go Lambda¶
Prerequisites and installation¶
Use Go 1.26 or newer. The Lambda executable runs on provided.al2023; it does not require Node.js or Python. Build with CGO_ENABLED=0.
Public module tags have not been released yet. Until they exist, work from a local checkout and use the repository's go.work, which connects the independent modules. After the initial source upload, obtain a checkout with:
If you already have the local source tree, start in its root directory. Do not run go get [email protected] until that module's release tag exists. See module installation and versioning for independent-module usage.
Create utilities once¶
The example below is included directly from the maintained examples/basic/main.go source when the site builds.
package main
import (
"context"
stdlog "log"
"github.com/aws/aws-lambda-go/lambda"
"github.com/rambow-cloud/powertools-lambda-go/logger"
"github.com/rambow-cloud/powertools-lambda-go/tracer"
)
type Event struct {
Name string `json:"name"`
}
type Response struct {
Message string `json:"message"`
}
func main() {
appLog := logger.New(
logger.WithServiceName("hello"),
logger.WithErrorHandler(func(err error) {
stdlog.Printf("logging failed: %v", err)
}),
)
tr, err := tracer.New(
tracer.WithServiceName("hello"),
tracer.WithCaptureResponse(false),
tracer.WithErrorHandler(func(err error) {
stdlog.Printf("tracing failed: %v", err)
}),
)
if err != nil {
stdlog.Fatal(err)
}
handler := func(ctx context.Context, event Event) (Response, error) {
requestLog := appLog.WithContext(ctx)
if err := requestLog.Info("Handling request", logger.Fields{"name": event.Name}); err != nil {
stdlog.Printf("logging failed: %v", err)
}
return tracer.Capture(ctx, tr, "greet", func(ctx context.Context) (Response, error) {
_ = tr.PutAnnotation(ctx, "Operation", "greet")
return Response{Message: "Hello, " + event.Name}, nil
})
}
// Put the tracer outside the logger wrapper so logs receive the active span context.
lambda.Start(tracer.WrapHandler(tr, logger.WrapHandler(appLog, handler)))
}
Create Logger and Tracer before lambda.Start so configuration is reused across invocations. appLog is the Powertools Logger object; stdlog is Go's standard log package, used only for fallback error messages. Inside the handler, requestLog := appLog.WithContext(ctx) creates the invocation-bound Logger object used for Info calls. Put Tracer outside Logger and pass the invocation context into operations. Both wrappers reuse the same Commons invocation identity.
With the default INFO level, an event such as {"name":"Ada"} writes one structured application record with message: "Handling request", service: "hello", and name: "Ada", plus timestamp, Lambda identity, and active tracing fields. The handler returns {"message":"Hello, Ada"} separately; that response is not a log record. See the Logger examples and JSON output for the complete record shape and method usage.
Response capture is disabled in this example. Logging and trace metadata are explicit application decisions; avoid placing secrets in either.
Configure observability¶
These settings are useful starting points for the deployed function:
| Environment variable | Example | Purpose |
|---|---|---|
POWERTOOLS_SERVICE_NAME |
orders |
Default service name when no explicit option overrides it |
POWERTOOLS_LOG_LEVEL |
INFO |
Structured log threshold |
POWERTOOLS_LOGGER_LOG_EVENT |
false |
Keep full event logging disabled |
OTEL_EXPORTER_OTLP_ENDPOINT |
http://localhost:4318 |
OTLP/HTTP collector endpoint |
POWERTOOLS_TRACER_CAPTURE_RESPONSE |
false |
Disable handler response metadata |
The example explicitly sets its service name to hello. Change that option or omit it to use the environment default.
A collector must actually be running at the configured OTLP endpoint. The library does not install a Lambda layer. To send traces to AWS X-Ray, deploy an appropriate collector extension with the awsxray exporter and its required execution-role permissions; follow X-Ray through OpenTelemetry.
Build and package¶
Run from the repository root:
The packaging tool verifies static Linux ELF binaries, architecture metadata, and an executable bootstrap ZIP entry with mode 0755.
| Lambda architecture | Artifact |
|---|---|
x86_64 |
dist/lambda-amd64.zip |
arm64 |
dist/lambda-arm64.zip |
Deploy the matching ZIP using your infrastructure tooling with runtime provided.al2023. Invoke with {"name":"Ada"}; the example returns {"message":"Hello, Ada"}. Deployment and cloud invocation are separate from local builds and CI.
Local verification¶
The default runtime acceptance environment uses Docker. Follow the maintained local integration runner and local acceptance scope.
Outside Lambda, tracing is disabled unless you explicitly supply tracer.WithLocalTracing(true). A local collector is still required to export spans. POWERTOOLS_DEV=true enables readable local logs and disables tracing.