Image & Video Delivery (CDN + Transformations)

Why serving images directly from your own database is a massive architectural anti-pattern.

The idea

When a user uploads a 5MB profile picture, you should never store the file in your Postgres database as a BLOB, and your API server should never be the one serving it to other users. Doing so wastes expensive database disk space, clogs up your API server's network bandwidth, and causes massive latency for users far away from your server. Instead, media files belong in Object Storage (like AWS S3), and they must be served through a Content Delivery Network (CDN).

Step 1: The Bad Way. User uploads a 5MB image to the API server, which saves it in Postgres. Other users download it straight from the API. Network choked.

How it works (Blob Storage + Edge CDN)

The standard architecture has three parts: (1) The client uploads the file directly to Object Storage (S3) bypassing your API entirely using a Pre-Signed URL. (2) Your database only stores a text string: avatar_url: "s3://bucket/img.jpg". (3) When viewing the image, the user's browser requests it from a CDN Edge Node (like Cloudflare) located physically close to them. The CDN caches the image so S3 only has to serve it once.

// 1. Client requests upload permission
const presignedUrl = await api.get('/generate-upload-url');

// 2. Client uploads DIRECTLY to S3 (bypassing your API)
await fetch(presignedUrl, { method: 'PUT', body: imageFile });

// 3. To serve the image, you use a CDN that supports on-the-fly transforms
// URL requests a 100x100 WEBP version. The CDN creates and caches it!
<img src="https://cdn.example.com/images/img.jpg?width=100&format=webp" />

Cost

Serving videos is exponentially harder than images. You cannot just serve an .mp4 file, because users on mobile networks need 480p, while users on WiFi want 1080p. Video requires Transcoding (converting the raw video into HLS or DASH formats). These formats chop the video into 2-second chunks, allowing the video player to seamlessly switch between 1080p and 480p chunks on-the-fly based on current bandwidth. This requires heavy background processing power when the video is uploaded.

Watch out for