Every app that accepts file uploads needs a way to stop one user from touching another user's files. Supabase Storage handles this with the same Row Level Security model as your tables, just applied to a hidden objects table sitting behind every bucket. You'll create a bucket, connect a real upload flow, and watch it fail the moment Row Level Security kicks in. From there you'll write a policy that gives each user their own folder and blocks anyone else from writing into it. By the end you'll have a storage bucket where every file is locked to the folder its owner created.
Who this is for: Anyone with a working Supabase project who wants file uploads that stay private to the person who made them.
By the end, you'll have:
What you'll learn:
3 objectives. One real outcome.
Objective 1
Create a new bucket, decide who can see its files by default, and put limits on what can be uploaded into it.
Objective 2
Connect a real app's upload flow to the bucket, watch it fail without a policy, then write an insert policy scoped to each user's own folder.
Objective 3
Upload to your own folder, then try someone else's folder and a nested subfolder to confirm the policy blocks what it should.
Do I need to write SQL from scratch for the storage policy?
No. You'll start from a template and adjust one comparison to match the folder structure this mission uses.
What's the real difference between a public and private bucket?
Public buckets let anyone with the file's URL open it directly. Private buckets need a signed URL or a passing policy before the file loads.
Why does the first upload fail before any policy exists?
Supabase Storage denies every request by default until a policy explicitly allows it. That failure means the security model is working, not that something's broken.
Does this same approach work for larger files like video?
Yes. The bucket limits and the policy logic stay the same, you just widen the allowed file size and mime types.