Supabase Storage Buckets

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

PublicPrivate
AccessAnyone with the URLRequires signed URL or valid JWT
Use caseAvatars, public assetsDocuments, 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

  1. RLS policies — SQL-based access rules using auth.uid()
  2. JOINs — query files alongside app data
  3. Triggers — react to uploads/deletes with Postgres functions
  4. 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

ApproachHowDrawback
bytea columnBinary data inline in a rowBloats DB, slow for large files
Large Objects (lo_*)Streaming blob storage with OIDsAwkward API, no RLS, complicates backups
File path as textStore path string in a columnPostgres 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 BucketFile Share (SMB/NFS/local)
Access controlRLS policies tied to JWT authOS-level ACLs/POSIX permissions
APIREST + client SDKsMount point / filesystem calls
ScalabilityScales with S3, CDN-readyLimited by disk/NAS capacity
MetadataQueryable in Postgres (JOINable)Filesystem metadata only
Offline accessNo — needs networkYes if locally mounted
IntegrationNative 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

When to Use What

If you need…Use
File access tied to app user authSupabase Storage
Public static asset servingCDN + S3 directly
Files for batch/local processingFile share or mounted volume
Simple app uploads without auth complexityS3 presigned URLs