Object storage (S3)
S3 buckets in France for your app’s files: images, exports, documents. They’re encrypted and versioned, and your app receives a key that works only for them.
Updated November 9, 2026.
You, to your agent: Add storage for the visit photos.
What your agent writes
Your agent writes it in while.yaml, at the root of your app:
buckets:
- name: uploads
What your app receives
Your app receives these environment variables at every deployment:
| Variable | What it holds |
|---|---|
S3_ENDPOINT | The S3 endpoint your app reaches. |
S3_REGION | The S3 region. |
AWS_REGION | The same, for the AWS SDKs. |
AWS_ENDPOINT_URL_S3 | The S3 endpoint, for the AWS SDKs. |
S3_BUCKET_UPLOADS | The name of the uploads bucket. |
S3_BUCKET | The name of the first bucket. |
AWS_ACCESS_KEY_ID | The access key, limited to the environment’s buckets. |
AWS_SECRET_ACCESS_KEY | Its secret. |
S3_ACCESS_KEY_ID | The same key, under another name. |
S3_SECRET_ACCESS_KEY | Its secret. |
S3_ENDPOINT_PUBLIC | The public S3 endpoint, for a presigned URL that a browser opens. |
When to use it
For files (images, exports, documents), rather than in the database.
How it works
Each declared S3 bucket is created in France, encrypted and versioned. The app receives the S3 endpoint, the name of its buckets and a key limited to its environment’s buckets.
What to know
An app with closed egress (the default) reaches its buckets through while’s S3 relay (S3_ENDPOINT, in the cluster). Through the relay, the key received is only valid for the environment’s buckets, and only from its pods. To read a bucket from a workstation, without a key, your agent uses the read_bucket tool.
A presigned URL for a browser is made on S3_ENDPOINT_PUBLIC, in path style (forcePathStyle), and the app’s addresses are allowed on it (CORS). For another origin, declare buckets: [{ name, cors: [https://…] }]. The public address takes presigned URLs to read or send an object (GET, HEAD, PUT, 5 GB at most), and presigned POST forms (createPresignedPost): the relay checks the policy (signature, expiration, bucket, key or its prefix, Content-Type, x-amz-meta-*) and counts content-length-range during the upload. A URL that signs content-length enforces the size: the relay checks the signature with it and passes Content-Length on as is; any other length is refused.
The bucket is created at deployment: it is a billed resource, approved like a database, and public: true (anonymous read) requires approval too. A replaced or deleted version of an object is kept 30 days. A preview has its own buckets, empty: nothing is copied. Buckets go with their environment, emptied, versions included. Object locking in compliance mode is not offered.
Pricing
These prices are the same on every plan, excluding VAT:
| Resource | Price | Details |
|---|---|---|
| Object storage | €0.25 per 10 GiB·month | requests included |
Your agent’s MCP tools
Your agent handles it with the get_app_status and read_bucket tools.