A bucket in Supabase is a named container in Supabase Storage — their S3-compatible object storage layer. It uses postgres for metadata and an S3-compatible backend for the actual file bytes.
How It Works
Client → Storage API → writes bytes to S3
→ writes metadata to Postgres
→ checks RLS policies via Postgres
Each file gets a path like bucket-name/folder/file.pdf
Metadata (filename, size, MIME type, owner, timestamps) lives in Postgres tables: storage.buckets and storage.objects
Binary content sits in the S3-compatible object store
Access controlled via Row Level Security (RLS) on storage.objects — same auth model as database tables
Bucket Types
Public
Private
Access
Anyone with the URL
Requires signed URL or valid JWT
Use case
Avatars, public assets
Documents, invoices, user uploads
PostgreSQL’s Role
Postgres acts as the metadata layer, not the file store. The storage schema has two key tables:
storage.buckets — one row per bucket (name, public/private flag, file size limits, allowed MIME types)
storage.objects — one row per file (bucket_id, path, size, MIME type, owner UUID, timestamps)
What Postgres Enables
RLS policies — SQL-based access rules using auth.uid()
JOINs — query files alongside app data
Triggers — react to uploads/deletes with Postgres functions
Foreign keys — reference storage.objects from app tables
What Postgres Does NOT Do
Store the file bytes (that’s S3)
Serve the files (a separate storage API service handles upload/download)
Vanilla Postgres Has No Built-in File Storage
Approach
How
Drawback
bytea column
Binary data inline in a row
Bloats DB, slow for large files
Large Objects (lo_*)
Streaming blob storage with OIDs
Awkward API, no RLS, complicates backups
File path as text
Store path string in a column
Postgres has no idea if the file exists
Supabase Storage is a separate open-source service (storage-api) — a Node.js server that handles uploads, writes bytes to S3, writes metadata to Postgres, and delegates auth to RLS.
Compared to a File Share
Supabase Bucket
File Share (SMB/NFS/local)
Access control
RLS policies tied to JWT auth
OS-level ACLs/POSIX permissions
API
REST + client SDKs
Mount point / filesystem calls
Scalability
Scales with S3, CDN-ready
Limited by disk/NAS capacity
Metadata
Queryable in Postgres (JOINable)
Filesystem metadata only
Offline access
No — needs network
Yes if locally mounted
Integration
Native to Supabase app (same auth)
Separate system, separate auth
Cons of the Supabase Storage Approach
Operational
Two systems to fail — S3 outage means files unavailable even if Postgres is fine
Backup complexity — must coordinate Postgres + S3 backups for consistent state
No cross-system transactions — upload + metadata insert are not atomic
Performance
RLS overhead — every file request hits Postgres to evaluate policies
Middleman latency — uploads go through the storage API vs direct-to-S3
Limitations
No built-in file versioning
No server-side processing (thumbnailing, transcoding, virus scanning)
Vendor coupling to Supabase’s schema and SDK patterns
Egress costs can surprise vs flat-rate NAS or self-hosted MinIO