Many applications need file uploads that should not be publicly accessible.
Examples include:
- Contracts
- Identity-related documents
- Internal reports
- Customer attachments
- Private invoices
Start With a Private Bucket
Create a storage bucket intended for private content.
Do not make sensitive files publicly accessible just because public URLs are easier to use.
User-Specific Paths
A simple organization can be:
users/
USER_ID/
document.pdf
This makes ownership easier to reason about.
Upload Permission
The database and storage policies should verify that the authenticated user is allowed to upload to the requested location.
Reading Files
Private files should require appropriate authorization.
Your application can request access only after verifying that the user should be able to see the file.
File Metadata
The database can store:
file_id
user_id
filename
storage_path
created_at
The actual file remains in Storage.
File Validation
Your application should also consider:
- File size
- File type
- Filename
- Upload limits
Do not blindly accept every uploaded file.
Production Checklist
Before launch:
Upload → Test
Read → Test
Unauthorized read → Test
Delete → Test
Different user → Test
Final Thoughts
Private file storage requires both correct bucket configuration and correct authorization policies.
Keep the file itself in Storage and the application's metadata in PostgreSQL.