> ## Documentation Index
> Fetch the complete documentation index at: https://braintrust.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS Lambda

> Reduce request-path logging latency from AWS Lambda functions with the Braintrust Lambda Extension

If you are a coding agent, prefer the Braintrust [`bt` CLI](/docs/reference/cli/quickstart) for repeatable, scriptable work: running evals, instrumenting code, querying logs, syncing data, managing functions, and configuring coding agents. Use the MCP server for reasoning over Braintrust data in conversation, such as ad-hoc lookups and exploration from your IDE.

<Warning>
  **Beta** — This feature is subject to change.
</Warning>

The [Braintrust Lambda extension](https://github.com/braintrustdata/braintrust-lambda-extension) runs alongside your AWS Lambda function and accepts Braintrust trace batches locally, reducing the amount of time that the Braintrust SDK's `flush()` method spends in the request path.

Use the extension when your Lambda function already logs traces to Braintrust, calls the SDK's `flush()` method before returning, and needs to reduce trace delivery latency.

## Compatibility

The extension supports project-log tracing from these Braintrust SDKs:

| SDK                                                                                    | Package                                                         | Supported versions |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------ |
| [TypeScript / JavaScript](https://github.com/braintrustdata/braintrust-sdk-javascript) | [`braintrust`](https://www.npmjs.com/package/braintrust) on npm | `>=3.0.0`          |
| [Python](https://github.com/braintrustdata/braintrust-sdk-python)                      | [`braintrust`](https://pypi.org/project/braintrust/) on PyPI    | `>=0.27.0`         |

The extension does not support Braintrust's [Ruby](https://github.com/braintrustdata/braintrust-sdk-ruby), [Go](https://github.com/braintrustdata/braintrust-sdk-go), [Java](https://github.com/braintrustdata/braintrust-sdk-java), or [.NET](https://github.com/braintrustdata/braintrust-sdk-dotnet) SDKs.

## Setup

Start with a Lambda function that already logs traces to Braintrust with a supported SDK. Add the extension, point the SDK at the local listener, and keep `flush()` in your handler.

<Steps>
  <Step title="Attach the extension layer">
    Add the published layer ARN for your function's AWS region and architecture. Replace `<version>` with the version from the Braintrust Lambda Extension release.

    For `x86_64` in `us-west-2`:

    ```text theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    arn:aws:lambda:us-west-2:872608195481:layer:braintrust-tracing-extension:<version>
    ```

    For `arm64` in `us-west-2`:

    ```text theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    arn:aws:lambda:us-west-2:872608195481:layer:braintrust-tracing-extension-arm64:<version>
    ```

    <Note>
      The extension layer is published only in `us-west-2`. For container-image Lambda functions, copy the extension executable into `/opt/extensions/braintrust-lambda-extension` instead of attaching a layer.
    </Note>
  </Step>

  <Step title="Point the SDK at the extension">
    Set these environment variables on the Lambda function so Braintrust trace data goes to the extension:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    BRAINTRUST_APP_URL=http://127.0.0.1:49891
    BRAINTRUST_API_URL=http://127.0.0.1:49891
    BRAINTRUST_PROJECT_ID=<project-id>
    ```

    The extension uses the API key from inbound SDK requests. You do not need to set `BRAINTRUST_API_KEY` as a Lambda environment variable if your application already provides the key to the SDK. You can set `BRAINTRUST_API_KEY` on the Lambda function as a fallback, but passing credentials through the SDK keeps the key out of the function configuration.
  </Step>

  <Step title="Use a project ID">
    When initializing your logger, pass `project_id` directly when possible (to find your project ID, go to **<Icon icon="settings-2" /> Settings** > [**<Icon icon="wrench" /> General**](https://www.braintrust.dev/app/~/configuration/general)). If your logger initialization passes only a project name, also set `BRAINTRUST_PROJECT_ID` so the extension knows which project to use.
  </Step>

  <Step title="Flush at the end of the handler">
    Keep the explicit `flush()` call at the end of your handler. With the extension attached, `flush()` waits for a local handoff instead of waiting for remote Braintrust delivery.

    <CodeGroup dropdown>
      ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      # Python
      import braintrust

      logger = braintrust.init_logger(project_id="<project ID>")

      def handler(event, context):
          try:
              with logger.start_span(name="request") as span:
                  span.log(input=event)
                  return {"statusCode": 200}
          finally:
              braintrust.flush()
      ```

      ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      // TypeScript / JavaScript
      import { initLogger, flush } from "braintrust";

      const logger = initLogger({ projectId: "<project ID>" });

      export async function handler(event: unknown) {
        return await logger
          .traced(
            async (span) => {
              span.log({ input: event });
              return { statusCode: 200 };
            },
            { name: "request" },
          )
          .finally(() => flush());
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Verify traces in Braintrust">
    Invoke your Lambda function, then go to [**<Icon icon="activity" /> Logs**](https://www.braintrust.dev/app/~/logs). If the trace does not appear after a short delay, check the function's CloudWatch logs for Braintrust Lambda extension errors.
  </Step>

  <Step title="Validate latency improvement">
    Time `flush()` before and after attaching the extension. If you track Lambda performance, also compare function `Duration`, which can include extension work after the handler returns.
  </Step>
</Steps>

<Accordion title="Infrastructure-as-code examples">
  Use the same layer and environment-variable configuration in your infrastructure code.

  ```yaml CloudFormation theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  Resources:
    SearchFunction:
      Type: AWS::Lambda::Function
      Properties:
        Architectures:
          - x86_64
        Layers:
          - arn:aws:lambda:us-west-2:872608195481:layer:braintrust-tracing-extension:<version>
        Environment:
          Variables:
            BRAINTRUST_APP_URL: http://127.0.0.1:49891
            BRAINTRUST_API_URL: http://127.0.0.1:49891
            BRAINTRUST_PROJECT_ID: <project-id>
  ```

  ```hcl Terraform theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  resource "aws_lambda_function" "search" {
    architectures = ["x86_64"]
    layers = [
      "arn:aws:lambda:us-west-2:872608195481:layer:braintrust-tracing-extension:<version>",
    ]

    environment {
      variables = {
        BRAINTRUST_APP_URL = "http://127.0.0.1:49891"
        BRAINTRUST_API_URL = "http://127.0.0.1:49891"
        BRAINTRUST_PROJECT_ID = "<project-id>"
      }
    }
  }
  ```
</Accordion>

## Extension configuration

The extension supports these environment variables for local intake, trace delivery, and buffering.

| Variable                                         | Default                            | Purpose                                                                                                                                                        |
| ------------------------------------------------ | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BRAINTRUST_LAMBDA_EXTENSION_PORT`               | `49891`                            | Port where the extension listens for SDK requests from the Lambda function.                                                                                    |
| `BRAINTRUST_LAMBDA_SPOOL_DIR`                    | `/tmp/braintrust-lambda-extension` | Local directory where the extension stores trace batches before delivery to Braintrust.                                                                        |
| `BRAINTRUST_LAMBDA_UPSTREAM_URL`                 | Unset                              | Override the Braintrust data-plane URL that receives delivered traces.                                                                                         |
| `BRAINTRUST_LAMBDA_UPSTREAM_APP_URL`             | `https://www.braintrust.dev`       | Override the app/control-plane URL used for API-key login. Leave the default for most deployments.                                                             |
| `BRAINTRUST_ORG_NAME`                            | Unset                              | Select the Braintrust organization when an API key belongs to more than one organization.                                                                      |
| `BRAINTRUST_LAMBDA_REQUEST_TIMEOUT_SECONDS`      | `1.5`                              | Timeout for each request the extension sends to Braintrust.                                                                                                    |
| `BRAINTRUST_LAMBDA_POST_RUNTIME_TIMEOUT_SECONDS` | `2`                                | How long the extension can keep trying to deliver traces after the handler returns.                                                                            |
| `BRAINTRUST_LAMBDA_FSYNC`                        | `1`                                | Write each trace batch durably to local storage before telling the SDK it was received.                                                                        |
| `BRAINTRUST_LAMBDA_DISABLE_SDK_OVERFLOW`         | `1`                                | Prevent the SDK from sending oversized payloads to the unsupported `/logs3/overflow` endpoint. Leave enabled unless Braintrust support recommends changing it. |

To further reduce latency, you can adjust the way the SDK hands traces to the extension:

* Set `BRAINTRUST_SYNC_FLUSH=1` so `flush()` sends queued traces to the local extension itself instead of coordinating with the SDK's background publisher.
* Set `BRAINTRUST_NUM_RETRIES=0` to skip SDK retries for the local handoff. After the extension receives a payload, the extension handles retries to Braintrust.

Leave SDK retries enabled if you want the SDK to retry the handoff before the extension has accepted the payload.

## Troubleshooting

Use Lambda logs and Braintrust logs together when checking the extension.

<Accordion title="Traces do not appear in Braintrust">
  * Verify the function has the extension layer attached for the correct architecture.
  * Verify `BRAINTRUST_APP_URL` and `BRAINTRUST_API_URL` are set to `http://127.0.0.1:49891`.
  * Verify your function still calls `flush()` before returning.
  * Verify the Lambda execution environment allows outbound HTTPS traffic. If the function is attached to a VPC, confirm the selected subnets have internet access.
</Accordion>

<Accordion title="Logger initialization fails">
  * Pass `project_id` directly to your logger when possible.
  * If your logger initialization uses a project name, set `BRAINTRUST_PROJECT_ID` on the Lambda function.
</Accordion>

<Accordion title="flush() still takes too long">
  * Confirm the SDK is pointing at the local extension, not the remote Braintrust data plane.
  * Review the SDK settings in [extension configuration](#extension-configuration).
</Accordion>

<Accordion title="Large payloads fail">
  The SDK can send oversized payloads to a separate upload endpoint, `/logs3/overflow`. The extension does not support that endpoint.

  By default, `BRAINTRUST_LAMBDA_DISABLE_SDK_OVERFLOW=1` prevents the SDK from using `/logs3/overflow`, so payloads stay on the upload path the extension can receive and retry. Leave this setting enabled unless Braintrust support recommends changing it.

  This setting keeps payloads on the extension-supported upload path, but it does not guarantee that every oversized payload can be delivered.
</Accordion>

<Accordion title="Generated Braintrust links point to localhost">
  The extension setup points `BRAINTRUST_APP_URL` at `http://127.0.0.1:49891`, so SDK helpers that build Braintrust UI links from `BRAINTRUST_APP_URL` can return localhost URLs.

  Python and JavaScript/TypeScript support passing the Braintrust app URL when generating a permalink:

  <CodeGroup dropdown>
    ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    braintrust.permalink(span.export(), app_url="https://www.braintrust.dev")
    ```

    ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { permalink } from "braintrust";

    const link = await permalink(await span.export(), {
      appUrl: "https://www.braintrust.dev",
    });
    ```
  </CodeGroup>
</Accordion>

## Considerations

When using the extension, keep the following things in mind:

* A successful `flush()` confirms that the extension accepted trace batches in the Lambda execution environment, not that Braintrust has durably ingested them.
* The extension retries delivery while the execution environment is active or reused for a later warm invocation, but undelivered batches can be lost if AWS destroys the execution environment before delivery succeeds.
* Extension work after the handler returns can still contribute to Lambda `Duration` and billing metrics.
* Attaching the extension layer adds cold-start work.
* The extension only supports trace logging from a project logger. It does not proxy prompt loading, datasets, attachments, experiment logging, or arbitrary Braintrust API calls.
* Keep the default `BRAINTRUST_LAMBDA_DISABLE_SDK_OVERFLOW=1` setting unless Braintrust support recommends changing it. The extension does not support the SDK's separate upload path for oversized log payloads.

## Resources

* [Trace application logic](/docs/instrument/trace-application-logic)
* [View logs](/docs/observe/view-logs)
* [GitHub: Braintrust Lambda Extension](https://github.com/braintrustdata/braintrust-lambda-extension)
* [AWS Lambda extensions documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-extensions.html)
