← 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

  1. Client requests a presigned upload URL from your API.
  2. API generates a random key, signs a PUT URL (TTL 5 min).
  3. Client uploads directly to object storage via the signed URL.
  4. Client notifies API on success; API inserts blob row.

Read flow

  1. Client requests blob by ID from your API.
  2. API checks ownership, generates a presigned GET URL (TTL 1 h).
  3. Client fetches directly or renders the URL in an img tag.
  4. 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.