Documentation
¶
Overview ¶
Package metadata reads the Lambda Metadata Endpoint: what Lambda knows about the execution environment a function runs in, such as the ID of its Availability Zone.
Usage ¶
md, err := metadata.Get(ctx)
if err != nil {
return err
}
logger.Info("serving", "az_id", md.AvailabilityZoneID) // "use1-az1"
An Availability Zone ID names the same physical zone in every account, so a function can prefer the replica of a cache or a database in its own zone. Converting it to a zone name (us-east-1a) takes ec2:DescribeAvailabilityZones.
The first call asks the endpoint, a local HTTP server Lambda runs in every execution environment (GET http://$AWS_LAMBDA_METADATA_API/2026-01-15/metadata/execution-environment, authenticated with the bearer token in AWS_LAMBDA_METADATA_TOKEN), with a one second timeout (WithTimeout). The answer cannot change during the environment's life, so it is cached until the process ends; calling Get in main has it ready before the first invocation. Fields AWS adds to the response later are in LambdaMetadata.Raw.
Outside Lambda ¶
When AWS_LAMBDA_INITIALIZATION_TYPE is not set (tests, local runs) or POWERTOOLS_DEV is on, Get returns empty metadata and no error, without a request, so that code using it needs no setup to run anywhere. To test with real values, point AWS_LAMBDA_METADATA_API at an httptest.Server, set AWS_LAMBDA_INITIALIZATION_TYPE and AWS_LAMBDA_METADATA_TOKEN, and call ClearCache between cases.
Errors ¶
A failure is a *LambdaMetadataError, with the HTTP status when the endpoint answered, wrapping ErrNoEndpoint, ErrNoToken, ErrStatus, ErrResponse or the transport's error. Failures are not cached.
Environment variables ¶
AWS_LAMBDA_METADATA_API the endpoint's address, set by Lambda AWS_LAMBDA_METADATA_TOKEN the endpoint's token, set by Lambda AWS_LAMBDA_INITIALIZATION_TYPE set by Lambda: Get runs in Lambda POWERTOOLS_DEV on: Get returns empty metadata
Concurrency ¶
Lambda Managed Instances start several invocations at once in one process. Concurrent first calls share one request to the endpoint; each returns when it completes, or when its own context ends.
Differences from Powertools Python ¶
- get_lambda_metadata is Get, which takes a context; its timeout is an option. clear_metadata_cache is ClearCache.
- POWERTOOLS_DEV is read like every other Powertools truth value (true, 1, yes, on, ...), where Python's metadata utility accepts only "true" and "1".
- The cache is safe for concurrent use, and concurrent first calls share one request.
- A response that is not a JSON object (null, an array) is an ErrResponse, where Python fails with an unrelated TypeError.
- Python's SnapStart cache invalidation has no Go counterpart: SnapStart does not run the provided runtimes Go functions use.
Index ¶
Examples ¶
Constants ¶
const ( // APIVersion is the version of the endpoint's API the package speaks. APIVersion = "2026-01-15" // Path is where the endpoint serves the execution environment's metadata. Path = "/metadata/execution-environment" // DefaultTimeout bounds a request to the endpoint, as in Powertools // Python. DefaultTimeout = time.Second )
The Lambda Metadata Endpoint, as the Lambda developer guide documents it.
Variables ¶
var ( // ErrNoEndpoint reports that AWS_LAMBDA_METADATA_API is not set. ErrNoEndpoint = errors.New("environment variable " + env.LambdaMetadataAPI + " is not set") // ErrNoToken reports that AWS_LAMBDA_METADATA_TOKEN is not set. ErrNoToken = errors.New("environment variable " + env.LambdaMetadataToken + " is not set") // ErrStatus reports a response other than 200 OK; StatusCode says which. ErrStatus = errors.New("unexpected status") // ErrResponse reports a response body that is not a JSON object. ErrResponse = errors.New("the response is not a JSON object") )
Sentinel errors, wrapped in a LambdaMetadataError.
Functions ¶
func ClearCache ¶
func ClearCache()
ClearCache forgets the cached metadata, so that the next Get asks the endpoint again. Tests use it between cases.
Types ¶
type LambdaMetadata ¶
type LambdaMetadata struct {
// AvailabilityZoneID is the Availability Zone ID the environment runs in,
// such as "use1-az1": the same physical zone in every account, unlike an
// Availability Zone name.
AvailabilityZoneID string `json:"AvailabilityZoneID"`
// Raw is the whole response of the endpoint, for the fields AWS adds
// after this package was written.
Raw jsontext.Value `json:"-"`
}
LambdaMetadata describes the execution environment the function runs in.
func Get ¶
func Get(ctx context.Context, opts ...Option) (LambdaMetadata, error)
Get returns the metadata of the execution environment. The first call asks the Lambda Metadata Endpoint; the answer is cached for the life of the environment, so later calls cost nothing. Call it in main to have it ready before the first invocation.
Outside Lambda (AWS_LAMBDA_INITIALIZATION_TYPE unset, in tests and local runs) and when POWERTOOLS_DEV is on, Get returns empty metadata and no error, without a request. A failure is a *LambdaMetadataError and is not cached: the next call asks again.
Concurrent calls share one request; each returns when it completes or when its own ctx ends. The options of the call that starts the request apply.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"os"
"strings"
"github.com/alessandrolattao/powertools-lambda-go/metadata"
)
func main() {
// In Lambda, Get asks the Lambda Metadata Endpoint once and caches the
// answer; here a local server plays the endpoint.
endpoint := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write([]byte(`{"AvailabilityZoneID":"use1-az1"}`)) //nolint:errcheck // a test server
}))
defer endpoint.Close()
lambdaEnv := map[string]string{
"AWS_LAMBDA_INITIALIZATION_TYPE": "on-demand",
"AWS_LAMBDA_METADATA_API": strings.TrimPrefix(endpoint.URL, "http://"),
"AWS_LAMBDA_METADATA_TOKEN": "token",
}
for name, value := range lambdaEnv {
_ = os.Setenv(name, value) //nolint:errcheck // valid names
}
defer func() {
for name := range lambdaEnv {
_ = os.Unsetenv(name) //nolint:errcheck // valid names
}
metadata.ClearCache()
}()
md, err := metadata.Get(context.Background())
if err != nil {
panic(err)
}
fmt.Println(md.AvailabilityZoneID)
}
Output: use1-az1
Example (OutsideLambda) ¶
package main
import (
"context"
"fmt"
"github.com/alessandrolattao/powertools-lambda-go/metadata"
)
func main() {
// Outside Lambda there is no endpoint: Get returns empty metadata, so
// code that uses it runs in tests and on a laptop unchanged.
md, err := metadata.Get(context.Background())
fmt.Printf("%q %v\n", md.AvailabilityZoneID, err)
}
Output: "" <nil>
type LambdaMetadataError ¶
type LambdaMetadataError struct {
// StatusCode is the HTTP status the endpoint answered with, or 0 when it
// did not answer.
StatusCode int
// Err is the cause.
Err error
}
LambdaMetadataError reports that the metadata could not be fetched.
func (*LambdaMetadataError) Error ¶
func (e *LambdaMetadataError) Error() string
func (*LambdaMetadataError) Unwrap ¶
func (e *LambdaMetadataError) Unwrap() error
type Option ¶
type Option func(*config)
Option configures Get.
func WithHTTPClient ¶
WithHTTPClient sends the request through client instead of a plain http.Client.
func WithTimeout ¶
WithTimeout bounds the request to the endpoint, DefaultTimeout by default.