Best file uploads for a vibe-coded app: Supabase Storage vs Vercel Blob
Your AI-built app needs people to upload photos or files, and you want them stored privately somewhere other than your server's disk, with big files going straight to storage.
- Our pick
- Supabase Storage96/100won on tie-breaker
- Why
- Passed every check on both runs. New buckets are private unless you opt in, and the storage itself rejected a file type we hadn't allowed. You can take your files with you through its S3-compatible API. It won a 96–96 tie on safe defaults.
- Not for you if
- your app is hosted on Vercel and you'd rather not add another account (Vercel Blob, 96/100, is the simpler fit).
Short answer: Use Supabase Storage (96/100) if you want private-by-default buckets, type and size limits enforced by the storage itself, and an S3-compatible API you can export with. Send Cache-Control: no-store from your Edge Function, or a deleted file can keep showing up. Pick Vercel Blob (96/100) if your app already runs on Vercel. It passed everything with the least friction, but choose private storage explicitly, because its API makes new stores public by default.
The verdict
Winner
Supabase Storage
won on tie-breaker
File storage with private buckets, signed links and an S3-compatible API, part of Supabase.
Passed all 8 checks on both runs. Buckets are private unless you opt in, a stranger with the public key couldn't read, list or upload anything, and the bucket itself rejected an HTML file. Files can leave through its S3-compatible API. 62 lines in one Edge Function. One gotcha cost it docs points: the CDN in front of Edge Functions cached our redirect, so a deleted file still resolved until we sent Cache-Control: no-store. Score: 96/100 (both runs), winning a tie with Vercel Blob on safe defaults.
Runner-up
Vercel Blob
Vercel's file storage, with private stores and direct-from-browser uploads.
Passed all 8 checks on both runs with no surprises, and its docs answered everything. A private store refused every request without a token, and Vercel's API rejected an HTML file we hadn't allowed. But its REST API creates public stores unless you ask for private, and there's no S3 API or bulk export. Score: 96/100 (both runs), tied with Supabase and second on our safe-defaults tie-breaker.
On this page
Quick answers
What's the best way to add file uploads to a vibe-coded app?
In our test, Supabase Storage and Vercel Blob tied at 96/100 on free plans. Both stored, listed, served and deleted files through our app, took a 10 MB image straight from the client, and refused an HTML file we hadn't allowed. Supabase won the tie on safe defaults (private buckets unless you opt in) and has an S3-compatible API for exporting. Vercel Blob is the easier pick if you already host on Vercel.
Are Supabase Storage buckets public by default?
No. A new bucket is private unless you mark it public. In our test, a stranger with only the project's public key couldn't read, list or upload files in our private bucket. They got 'Bucket not found' on the public URL pattern, an empty list, and a row-level-security refusal on upload.
Is Vercel Blob private by default?
Not through its API. The dashboard and CLI make you choose private or public, but Vercel's REST API (which AI agents and Vercel's MCP use) creates a public store when you leave out the access setting. Ask for a private store explicitly. Our private store refused every request without a token.
Can a browser upload big files straight to storage?
Yes, with both. Your server issues a short-lived permission first: a signed upload URL on Supabase, a client token on Vercel. The browser then sends the file directly to storage. Our 10 MB image uploaded this way on both, and both rejected an HTML file because we'd limited uploads to JPEG and PNG.
Can I move my files out later?
Supabase Storage has an S3-compatible API, so standard S3 tools can copy everything out. Vercel Blob has no S3 API. Its CLI lists files and downloads them one at a time, so a full export takes a small script.
Why
Who this is for: your app works, usually built with AI, and now people need to upload things: profile photos, receipts, documents. You want the files stored privately, off your server’s disk, served back only through your app, with big files going straight from the browser to storage.
Our pick: Supabase Storage (96/100). It passed every check on both runs. Its buckets are private unless you opt in, and the bucket itself refused a file type we hadn’t allowed. A stranger holding the project’s public key couldn’t read, list or upload anything. If you ever leave, its S3-compatible API works with standard S3 tools.
Runner-up: Vercel Blob (96/100). It also passed everything, with the fewest surprises and the clearest docs of the two. It’s the natural choice if your app is hosted on Vercel. Two things put it second: Vercel’s API makes new stores public unless you ask for private, and there’s no S3 API or bulk export.
It’s a tie. Both scored 96 on both runs, so we ran each a second time, as our rubric requires. The tie-breaker is safe defaults, which Supabase wins.
Gotchas
Supabase: send Cache-Control: no-store from Edge Functions. In our first run, after we deleted a file, our upload API kept redirecting to it. The function code was right. The CDN in front of Edge Functions had cached our earlier redirect because the response had no Cache-Control header (cf-cache-status: HIT). We didn’t find this in the docs. Fix: set Cache-Control: no-store on API responses that change.
Supabase: a signed link can outlive a delete. In our re-run, a 60-second signed link we’d handed out before the delete kept serving the deleted file until it expired, about 55 s later. Fix: keep signed links short-lived, or stream private files through your app as we did with Vercel.
Vercel Blob: ask for private explicitly. The dashboard and CLI make you choose private or public. Vercel’s REST API, which AI agents and Vercel’s MCP use, defaults to public when you leave the setting out. Tell your AI tool to create a private store. In a private store, files can’t be fetched without a token (we got 403).
Both: approve direct uploads on your server. Big files go straight from the browser to storage, but only after your server hands out a short-lived permission (Supabase: a signed upload URL; Vercel: a client token). Check the user is logged in before issuing it. Both vendors’ docs say so. Our test app skipped login to keep the test equal.
Scores
Scored with our published rubric. Tested 2026-10-16. Both tools scored the same on both runs.
| Criterion | Supabase Storage | Vercel Blob |
|---|---|---|
| Task success (35) | 5 (8 of 8) | 5 (8 of 8) |
| Effort (15) | 5 (1 issue: cached function response) | 5 |
| Time (10) | 5 | 5 |
| Cost (10) | 5 | 5 |
| Quality, docs and developer experience (10) | 3 (3 of 5: cache gotcha not in docs; pricing page doesn’t say what happens at the limit) | 5 (5 of 5) |
| Ownership (10) | 5 (S3-compatible API) | 4 (CLI downloads one file at a time) |
| Safe defaults (10) | 5 (4 of 4) | 4 (3 of 4: API defaults to public) |
| Total | 96 (both runs) | 96 (both runs) |
The 8 checks: upload, download with a matching checksum, list with the right size, delete (then a 404, and any earlier storage link dead within 60 s), no secret in the browser, strangers can’t read, list or upload, a 10 MB image sent straight to storage, and an HTML file rejected by the storage itself.
What it costs
All runs cost $0 on the free plans, with no card.
- Supabase Free: 1 GB file storage, 5 GB egress plus 5 GB cached egress, 50 MB max upload size. Free projects pause after 1 week of inactivity, with a limit of 2 active projects. Pro starts at $25/month (checked 2026-10-16).
- Vercel Blob on Hobby: 1 GB storage a month, 10,000 simple and 2,000 advanced operations, 10 GB data transfer, shared with your other Vercel usage. You’re never charged on Hobby. If you go over, Blob stops working until 30 days pass (checked 2026-10-16).
Caveats
- Different setups, same API. Each tool ran the same upload API the way its docs suggest: Supabase in a Supabase Edge Function, Vercel Blob in Vercel Functions. Supabase hands out a short-lived storage link on download. With Vercel we streamed files through the app, as Vercel’s private-storage docs show. Upload speeds are logged in the evidence but not scored.
- Order matters. Supabase ran first, so Vercel’s run reused the check script and lessons.
- Vercel test project. We couldn’t create a new Vercel project with our access, so the Vercel runs used a preview deployment of an existing test project. Details are in the test script’s amendments.
- No login in the test app. Both apps let anyone call the upload API, to keep the comparison equal. Add login before you launch: see adding login to your app.
- Runs were done by an AI agent following vendor docs only.
Next step: put the files’ details in a database. See our tested pick for a database for your vibe-coded app. Charging for downloads? See taking payments in your app.
Before you launch: check your app’s security. See our vibe coding security check.
Not tested yet
- Cloudflare R2. It has to be turned on in Cloudflare’s dashboard first; queued for a person.
- Firebase Cloud Storage. Needs a console click to enable on our project; queued.
- Cloudinary and UploadThing. Both need a browser signup; queued.
Test log
| Date | Agent | Step | Result |
|---|---|---|---|
| Oct 16, 2026 | Lando (agent) | Supabase, run j07-supabase-r1. Private bucket on our free test project, limited to JPEG and PNG up to 20 MB. Upload API as a Supabase Edge Function using the injected secret key (62 lines). Ran the 8 checks. | First pass: everything except delete. After a delete, our API still redirected to the file. The response showed a CDN cache hit: the CDN in front of Edge Functions had cached our redirect. We added Cache-Control: no-store and all checks passed. Working in 2 min 36 s. $0. |
| Oct 16, 2026 | Lando (agent) | Supabase: stranger probes with only the project URL and public key. | Public URL pattern: 'Bucket not found'. Direct read: 'Object not found'. List: empty. Upload and signed-upload requests: refused by row level security. |
| Oct 16, 2026 | Lando (agent) | Vercel Blob, run j07-vercel-r1. Private store connected to a Vercel project through the Vercel MCP. Upload API as three Vercel Functions (70 lines) using Vercel's put, get, list, del and handleUpload. Ran the 8 checks. | All checks passed on the first run. Working in 2 min 27 s, including a detour of ours: we couldn't create a new Vercel project, so we used our existing test project. $0. Files stream through our app, so no storage link is ever handed out. |
| Oct 16, 2026 | Lando (agent) | Vercel Blob: stranger probes without a token. | Private file URL: 403. List and upload API: 403 'Cannot get token'. A made-up store address got 404, which confirms the 403 came from our store. |
| Oct 16, 2026 | Lando (agent) | Re-runs (rubric: top two within 10 points). Supabase j07-supabase-r2 on a new bucket, Vercel j07-vercel-r2 on a fresh deployment, same code. | Both passed all checks again: Supabase in 1 min 16 s, Vercel in 30 s. One Supabase detail: a signed link handed out before a delete kept serving the deleted file for about 55 s, until the link's own 60-second expiry. Both scored 96 again. |
Affiliate disclosure
This page has no affiliate links yet. Every link goes to the tool’s own homepage. Affiliate deals never decide a pick, and a tool with no affiliate program can still win. How we make money.
Sources
- Test script and amendments (BuildWithThis)
- Supabase pricing (checked 2026-10-16)
- Supabase Storage pricing (checked 2026-10-16)
- Supabase billing FAQ, exceeding Free Plan quota (checked 2026-10-16)
- Supabase Storage S3 compatibility (checked 2026-10-16)
- Vercel Blob usage and pricing (checked 2026-10-16)
- Vercel Blob private storage (checked 2026-10-16)
- Vercel Blob client uploads (checked 2026-10-16)
- Vercel REST API, create a Blob store (access defaults to public) (checked 2026-10-16)
- Vercel acceptable use policy, benchmarking (checked 2026-10-16)
What to use now
A free weekly email.
We'll email you a link to confirm. We use Kit to send the email. Unsubscribe anytime. Privacy