Skip to main content
An application’s filesystem on Sevalla resets on every deployment, so files that users upload belong in a Sevalla object storage bucket. FastAPI talks to the bucket through its S3-compatible API with boto3, the AWS SDK for Python.

At a glance

Environment variables

This guide adds four variables to the ones in Deploy a FastAPI application. The application doesn’t start without them.

Before you begin

Create a bucket

In the sidebar, click Object storage, then click Create object storage. Enter storefront-media as the Name, choose the Location closest to the application, and click Create object storage. Keep it private: the code in this guide shares each file through a presigned URL that expires.

Add the bucket details to the application

The values come from the bucket’s Settings tab. See Connect with the S3 API for each one.
A bucket's Settings tab with the display name, location, bucket name, ID and endpoint, and the access key and secret keyA bucket's Settings tab with the display name, location, bucket name, ID and endpoint, and the access key and secret key
1

Open the environment variables

In the sidebar, click Applications, then click the application. Click the Environment variables tab.
2

Add the variables

Click Add environment variables. Add the variables, keep Available during runtime selected, and click Add environment variables.
The variables apply with the next deployment. Add them before you deploy the code: the application doesn’t start without them.

Install boto3

Install boto3 and update requirements.txt:

Add the S3 client

Create the client from environment variables. Cloudflare R2, which runs Sevalla’s object storage, uses the region auto:
app/storage.py

Upload and list files

Add the imports to the top of app/main.py and the two routes to the end. Uploads use FastAPI’s UploadFile, which fastapi[standard] supports. The routes are plain def functions, so FastAPI runs boto3’s blocking calls in a thread pool:
app/main.py
Each URL works for 1 hour. list_objects_v2 returns up to 1,000 objects per call; pass ContinuationToken for more. See presigned URLs. For a public bucket, link files on its public domain instead; see public URLs. Commit and push the changes. If Auto-deploy is off, click Deploy now on the application’s Overview tab.

Verify

Upload a file and list the bucket, with your application’s domain:
The first response is {"filename":"hello.txt"}. The second lists hello.txt with a url: open it, and the page reads Hello from Sevalla. In the sidebar, click Object storage, click the bucket, and the Objects tab lists hello.txt. See Manage objects. To check the same from a script, read the file back through its presigned URL, and list the bucket with List objects (listObjectStorageObjectsV3), with BUCKET_ID from Deploy with the API:

Deploy with the API

These calls create the bucket, add its variables and deploy the code, as the dashboard steps on this page do. APP_ID is the application from Deploy with the API in the deploy guide, with auto-deploy on, and SEVALLA_API_KEY holds the same API key. Commit the code from this page first, without pushing it, and run the commands in the project folder: the application doesn’t start until the variables exist, so the push comes last.
1

Create the bucket

Create object storage bucket (createObjectStorageV3). Its response is the only one that contains the access key and the secret key, so keep it:
location is a hint for where most requests come from: weur (Western Europe) suits an application in Frankfurt, and enam (Eastern North America) one in Ashburn. CLI: sevalla object-storage create --name storefront-media --location weur --json. MCP: sevalla_api_create with createObjectStorageV3 and the same body.
2

Add the variables

Create environment variable (createEnvironmentVariableV3), once per variable, available during runtime only:
It prints one line per variable, such as {"key":"S3_BUCKET","is_runtime":true,"is_buildtime":false}. CLI: sevalla apps env-vars create "$APP_ID" --key S3_BUCKET --value "$S3_BUCKET", and the same for the others; the CLI makes them available during build and runtime. MCP: set_environment_variables with all four, runtime true and buildtime false.
3

Push and find the deployment

Push the commit. Auto-deploy starts a deployment of it, and List deployments (listDeploymentsV3), newest first, returns it once it exists:
With auto-deploy off, start it with Trigger deployment (triggerDeploymentV3) instead. CLI: sevalla apps deployments list --app-id "$APP_ID". MCP: list_deployments.
4

Wait for the deployment

Get deployment (getDeploymentV3) until status is success or failed:
It prints success when the deployment finishes, or failed; after 30 minutes without either, it prints the status it last read. CLI: sevalla apps deployments get "$DEPLOYMENT_ID" --app-id "$APP_ID". MCP: get_deployment, then get_deployment_logs if it failed.
Then run the checks in Verify, with the domain from List application domains (listApplicationDomainsV3) as in the deploy guide.