# How to add file uploads to your app.

URL: https://antideploy.com/blog/how-to-add-file-uploads-to-your-app

Files saved to your app's disk disappear on the next deploy. A private S3 bucket keeps them, and your agent creates it for you.

## At a glance

- **A private bucket**: One per app, in Singapore
- **A key for one bucket**: It reaches nothing else
- **Browsers upload directly**: Through a presigned URL
- **Disk is temporary**: Flagged before it builds

Published 7 October 2026. Facts checked 7 October 2026. 3 min read.

## The short answer

To add file uploads, tell your connected coding agent to create a bucket and save uploads to it. Antideploy creates a private S3 bucket for your app, writes its variables into your `.env` without printing the key, and gives the running app the same variables. Any S3 client works with it. Never save uploads to the app's own disk, because the disk is replaced on every deploy.

> **Say this to your coding agent**
>
> Add file uploads to this project and store the files in a bucket.

If your agent is not connected yet, paste this first: Set this project up to deploy on Antideploy. Fetch https://antideploy.com/agent.md and follow it.

## Why not the disk

A container is replaced on every deploy and its disk goes with it. A user's avatar saved with `multer` or `fs.writeFile` is gone after the next deploy, and nothing will error. Antideploy flags code that saves uploads to disk before it builds anything. A bucket is not replaced, and it belongs to your application.

## What your agent does

### 1. It creates the bucket before it writes the upload code

So the upload is written and tested against the real thing. Asking twice returns the same bucket.

### 2. It writes the variables into your .env

The key goes into a file through a redirect that never prints it. The deploy that follows gives the running app the same variables.

### 3. Your code uses any S3 client

The AWS SDKs and boto3 read the `AWS_*` variables from the environment, so code that reads them and sets nothing else already works.

A project that uses an S3 client and brought no key of its own gets a bucket at its first deploy, even without asking.

## Upload straight from the browser

Have your server return a presigned PUT URL. The browser sends the file straight to the bucket, without passing through your app. Browsers on any origin may call the bucket, and every request still needs the key or a link signed with it.

**Node**

```
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const s3 = new S3Client({ forcePathStyle: true });
const url = await getSignedUrl(
  s3,
  new PutObjectCommand({ Bucket: process.env.BUCKET_NAME, Key: "avatars/maya.webp" }),
  { expiresIn: 300 },
);
// hand url to the browser, which PUTs the file straight to the bucket

# Python
import os, boto3

s3 = boto3.client("s3")
s3.upload_file("avatar.webp", os.environ["BUCKET_NAME"], "avatars/maya.webp")
```

## Showing a file to a visitor

The bucket is private, so there is no public URL. To show a file, serve it through your app, or hand the visitor a signed link that expires.

## What you get

- One private bucket per app, on Neon Object Storage in Singapore
- A key that reaches that bucket and nothing else
- Storage is not metered or capped today
- Buckets per account: 1 on Free, 2 on Go, 3 on Pro and 5 on Scale

## Here's where it stops.

A platform that only tells you what it is good at is one you find the edges of in production. These are the ones to know before your first deploy.

### The disk forgets

Anything written to local disk is gone on the next deploy. Apps that speak S3 get a bucket instead.

### One region

Everything runs in Singapore, with the database beside the app. Users far from Asia will see slower responses.

## Upload questions, answered.

Anything else? Write to us and a person answers.

[support@antideploy.com](mailto:support@antideploy.com)

### Which S3 clients work?

Any S3 client. Current AWS SDKs and boto3 choose path-style addressing by themselves for this bucket. In new JavaScript code, set `forcePathStyle: true` anyway.

### Can I use Cloudinary or UploadThing instead?

Yes. Antideploy only creates a bucket for code that uses an S3 client and brought no key of its own, and a key you set yourself is never replaced.

### Should I copy the variables into my secrets?

No. The platform sets them in the running app, and a copy could shadow the real ones.

### What if I reach my bucket limit?

Creating another answers with a plan-limit error, and your agent tells you. Nothing already created is affected. You can delete an application you no longer need, or move to a plan with more.

### Is there a public CDN?

No. Every object is private, and there is no built-in CDN.

## More guides, and the platform.

Each platform page covers one part of Antideploy: what it does, where it stops and the questions people ask. [See the whole platform](https://antideploy.com/platform), or [all the guides](https://antideploy.com/blog).

- [How to add a Postgres database to your app](https://antideploy.com/blog/how-to-add-a-postgres-database-to-your-app): Ask your agent. A Postgres 17 database is created beside your app and DATABASE_URL is set.
- [How to deploy a full-stack app](https://antideploy.com/blog/how-to-deploy-a-full-stack-app): A frontend, an API and a database. One app or two, and what to do about each piece.
- [Why does my app work on localhost but not online?](https://antideploy.com/blog/why-does-my-app-work-on-localhost-but-not-online): Nine common reasons, how to check each one, and how to fix it.

- [File storage](https://antideploy.com/platform/file-storage)
- [Environment variables](https://antideploy.com/platform/environment-variables)
- [Database](https://antideploy.com/platform/database)
- [Deployments](https://antideploy.com/platform/deployments)

Facts on this page were checked against the live platform on 7 October 2026.

## Deploy something. Start with one sentence.

Paste one sentence into your coding agent, click Approve once, and get a live link. No card, no trial clock.

To set this up, give your coding agent this sentence:

```text
Set this project up to deploy on Antideploy. Fetch https://antideploy.com/agent.md and follow it.
```
