Chapter 14: Blob Storage, Object Stores, and File Systems
Large binary data (images, videos, backups, logs) doesn't belong in a database. Use object storage.
Object Storage (S3-like)
// Store: PUT object with a key
PUT /bucket/images/user123/avatar.jpg → [binary data]
// Retrieve: GET by key
GET /bucket/images/user123/avatar.jpg → [binary data]
// Properties:
// - Flat namespace (no directories, just key prefixes)
// - Immutable (overwrite = new version)
// - Virtually unlimited storage
// - 99.999999999% durability (11 nines)
// - Cheap ($0.023/GB/month for S3 standard)
Pattern: Metadata in DB, Blob in Object Store
Upload flow:
1. Client → App: "upload photo"
2. App → S3: store blob, get URL
3. App → PostgreSQL: store metadata {id, user_id, s3_url, size, created_at}
4. App → Client: "done, URL is ..."
Download flow:
1. Client → App: "get photo 123"
2. App → PostgreSQL: lookup metadata → s3_url
3. Client → CDN/S3: fetch blob directly (or pre-signed URL)
Pre-Signed URLs
Let clients upload/download directly to S3 without going through your server:
// Server generates a time-limited signed URL
url = s3.generate_presigned_url('put_object', bucket='uploads', key='photo.jpg', expires=300)
// Client uploads directly to S3 using this URL
// Your server never handles the large file!
Key Takeaways
- Never store large blobs in your database — use object storage (S3)
- Store metadata in DB, blob in object store
- Pre-signed URLs let clients upload/download directly (saves server bandwidth)
- CDN in front of object storage for frequently-accessed files