← Back to docs
Recipe
Object/blob storage architecture
Scalable pattern for user-uploaded files, screenshots, and binary assets with signed URLs and CDN delivery.
Overview
Store user blobs in object storage (S3-compatible) behind short-lived signed URLs. Metadata lives in your primary database. A CDN sits in front for cached reads. This keeps your app server stateless and your database lean.
Data model
blobs id uuid pk user_id uuid fk → users key text (storage path) size bigint mime_type text created_at timestamptz
Upload flow
- Client requests a presigned upload URL from your API.
- API generates a random key, signs a PUT URL (TTL 5 min).
- Client uploads directly to object storage via the signed URL.
- Client notifies API on success; API inserts blob row.
Read flow
- Client requests blob by ID from your API.
- API checks ownership, generates a presigned GET URL (TTL 1 h).
- Client fetches directly or renders the URL in an img tag.
- CDN caches the response; subsequent reads hit the edge.
Key decisions
- Use random keys, never user-supplied filenames.
- Set short TTLs on signed URLs; rotate signing keys.
- Separate buckets by environment (dev/staging/prod).
- Enable object versioning for rollback safety.