The Metadata utility allows you to fetch data from the [AWS Lambda Metadata Endpoint (LMDS)](<https://docs.aws.amazon.com/lambda/latest/dg/configuration-metadata-endpoint.html>). This can be useful for retrieving information about the Lambda execution environment, such as the Availability Zone ID.

## Key features

- Fetch execution environment metadata from the Lambda Metadata Endpoint
- Automatic caching for the duration of the Lambda sandbox
- Graceful fallback to empty metadata outside Lambda (local dev, tests)
- Forward-compatible dataclass that can be extended as new fields are added

## Getting started

### Usage

You can fetch data from the Lambda Metadata Endpoint using the `get_lambda_metadata` function.

> [!TIP]
>
> Metadata is cached for the duration of the Lambda sandbox, so subsequent calls to `get_lambda_metadata` will return the cached data.

```
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.metadata import LambdaMetadata, get_lambda_metadata
from aws_lambda_powertools.utilities.typing import LambdaContext

logger = Logger()


def lambda_handler(event: dict, context: LambdaContext) -> dict:
    metadata: LambdaMetadata = get_lambda_metadata()
    az_id = metadata.availability_zone_id  # e.g., "use1-az1"

    logger.append_keys(az_id=az_id)
    logger.info("Processing request")

    return {"az_id": az_id}
```

You can also fetch metadata eagerly during cold start, so it's ready for subsequent invocations:

```
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.metadata import LambdaMetadata, get_lambda_metadata
from aws_lambda_powertools.utilities.typing import LambdaContext

logger = Logger()

# Fetch during cold start — cached for subsequent invocations
metadata: LambdaMetadata = get_lambda_metadata()


def lambda_handler(event: dict, context: LambdaContext) -> dict:
    logger.append_keys(az_id=metadata.availability_zone_id)
    logger.info("Processing request")

    return {"az_id": metadata.availability_zone_id}
```

### Available metadata

| Property | Type | Description |
| --- | --- | --- |
| `availability_zone_id` | `str` or `None` | The AZ where the function is running (e.g., `use1-az1`) |

## Testing your code

The metadata endpoint is not available during local development or testing. To ease testing, the `get_lambda_metadata` function automatically detects when it's running in a non-Lambda environment and returns an empty `LambdaMetadata` instance. This allows you to write tests without needing to mock the endpoint.

If you want to mock specific metadata values for testing purposes, you can patch the internal `_fetch_metadata` function and set the required environment variables:

```
from unittest.mock import patch

from aws_lambda_powertools.utilities.metadata import LambdaMetadata, clear_metadata_cache, get_lambda_metadata


def test_handler_uses_metadata(monkeypatch):
    # GIVEN a Lambda environment with metadata env vars
    monkeypatch.setenv("AWS_LAMBDA_INITIALIZATION_TYPE", "on-demand")
    monkeypatch.setenv("AWS_LAMBDA_METADATA_API", "127.0.0.1:1234")
    monkeypatch.setenv("AWS_LAMBDA_METADATA_TOKEN", "test-token")

    mock_response = {"AvailabilityZoneID": "use1-az1"}

    with patch(
        "aws_lambda_powertools.utilities.metadata.lambda_metadata._fetch_metadata",
        return_value=mock_response,
    ):
        # WHEN calling get_lambda_metadata
        metadata: LambdaMetadata = get_lambda_metadata()

        # THEN it returns the mocked metadata
        assert metadata.availability_zone_id == "use1-az1"

    # Clean up cache between tests
    clear_metadata_cache()


def test_handler_works_outside_lambda():
    # GIVEN no Lambda environment variables are set
    # WHEN calling get_lambda_metadata
    metadata: LambdaMetadata = get_lambda_metadata()

    # THEN it returns empty metadata without errors
    assert metadata.availability_zone_id is None
```

We also expose a `clear_metadata_cache` function that can be used to clear the cached metadata, allowing you to test different metadata values within the same execution context.
