Skip to main content

`--- title: Python SDK S3 presigned response handling boost: 0.5 category: config pylon_issue_id: ‘17978’ pylon_issue_uuid: ‘84291cf5-a0a5-4ce6-bfea-fa30f7642938’ assignee: “Josep” ‘og:image’: ‘https://www.braintrust.dev/og?template=docs&title=Python%20SDK%20S3%20presigned%20response%20handling’ ‘og:image’: ‘https://www.braintrust.dev/og?template=docs&title=Python%20SDK%20S3%20presigned%20response%20handling’ description: “Understand how Braintrust offloads large dataset and query responses to S3 presigned URLs and how to allowlist the host or reduce fetch size.”

Applies to:
  • Plan -
  • Deployment -

Summary

Large dataset/BTQL responses may be offloaded to S3 and redirected to, or resolved through, a presigned download URL. This happens when a single response page exceeds ~4 MB. Allowlist the specific response-bucket host or reduce fetch page size to avoid the offload.

What is happening

When a query or dataset fetch produces a large response page (around 4 MB per response page), Braintrust may store that page temporarily in S3 and return a presigned URL instead of inlining the rows. The SDK then performs a second GET to that URL to download the gzipped JSON payload. Presigned URLs are created only after authorization is checked. Each URL is scoped to the generated object and is short‑lived. The TTL is fixed at 1 hour. Treat the URL as a sensitive bearer link while valid. This offload pattern appears for larger data-query/fetch operations (dataset fetches, large SQL query results, large logs/traces, experiment results). Ordinary create/update/list API calls typically return inline and do not use this path.

Fix or suggestion

Option 1: Allowlist the response-bucket host (most common fix)

  1. Capture the host shown in the presigned URL returned by the API error (the full host portion).
  2. Add that host to your proxy/firewall allowlist. Also allow GETs to the returned key prefix, usually /responses/......
  3. Confirm your proxy does not strip or alter query parameters from the presigned URL.
Example host pattern guidance. Use the exact host you received; do not wildcard the entire region:
  • bt3subnets-3-lambdaresponsesbucket-{bucket-suffix}.s3.{aws-region}.amazonaws.com
  • Key prefix: /responses//.json.gz
Note: bucket name and region may vary by deployment. For EU data-plane organisations, the bucket host/region may differ from the US example. Allowlist the exact host your environment returned rather than hard-coding us-east-1 or wildcarding a whole S3 region.

Option 2: Keep responses inline by reducing fetch size

  1. Page or limit SQL query and dataset fetches so each page stays below the ~4 MB threshold.
  2. Use pagination or LIMIT/OFFSET (or your SDK’s pagination controls) to fetch smaller batches.
Minimal example (generic SQL pagination):
page_size = 1000
offset = 0
for row in dataset.fetch(batch_size=250):
    process(row)
Adjust page_size until responses are consistently under the threshold. The exact SDK parameters may differ. Use your SDK’s pagination options where available.

How to confirm it worked

  • Allowlist fix: re-run the failing fetch. The SDK should download the presigned URL successfully (HTTP 200) and no 403 from your proxy should occur.
  • Pagination fix: re-run the query and verify the API returns inline rows (no presigned URL in the response) and the SDK does not perform a secondary S3 GET.

Notes

  • The presigned URL expiry is fixed at 1 hour. There is no exposed customer setting to change it.
  • There is no published, stable global regex for response-bucket hosts. Use the exact host returned by your deployment for allowlisting.
  • Retention/cleanup schedule for the temporary S3 objects is not published. If you need an official host pattern, TTL change, or a way to force inline responses from the Python SDK, please file a feature request so product/engineering can evaluate it.