SD System Design In Depth
0%
lesson system-designimagescaching

Image CDN and resizing

Module 5.2: Media Processing & CDN Distribution Updated Sep 18, 2026
📄 Cheat Sheet
Build your own Cloudinary -  Image Optimisation on the fly
Piyush Garg Build your own Cloudinary - Image Optimisation on the fly Watch on YouTube ↗

Builds exactly this unit's architecture, URL-parameter driven on-the-fly resize and format conversion from an original in object storage behind a cache.

0:00 / --:--

On-the-Fly Image Processing vs. Batch Pre-Generation

Modern applications display images across hundreds of device resolutions, responsive breakpoints, and formats (WebP, AVIF, JPEG). Pre-generating and storing every dimension permutation multiplies storage costs (sizes x formats x densities). Modern media platforms generate resized variants on-demand at the CDN edge.

Dynamic Image Processing Pipeline

flowchart LR User["Browser Request: /img/banner.jpg?w=600&fmt=webp"] --> Edge["Cloudflare / CloudFront CDN Edge"] Edge -->|Edge Cache Hit| User Edge -->|Cache Miss| Serverless["Edge Worker / Image Resizing Lambda"] Serverless --> OrigCache["Original S3 Bucket"] Serverless --> Transform["Resize, Crop & Encode WebP"] Transform --> Edge Edge --> User

Edge Transformation Mechanics

  • Clients request images with query parameters: /images/profile.jpg?width=400&quality=80&format=webp.
  • The CDN edge checks if that exact transformed combination is cached. If yes, it returns it instantly from edge cache.
  • On cache miss, a lightweight serverless worker (e.g., Cloudflare Workers, AWS Lambda@Edge) fetches the original master image from S3, applies resizing using libvips/Sharp, stores the result in CDN cache, and serves the client.
  • Only accept an allowlist of widths and qualities (or signed transform URLs); otherwise arbitrary parameters let anyone force uncached, expensive resizes.

Worked example: pre-generate versus on demand

Ten million originals averaging 2 MB is 20 TB. Suppose the product uses 6 widths x 3 formats (JPEG, WebP, AVIF) x 2 pixel densities = 36 variants averaging 60 KB.

  • Pre-generate all: 10M x 36 x 60 KB = about 21.6 TB of extra storage, plus 360 million resize jobs up front, most for images that will never be viewed at that size.
  • On demand: if 80 percent of views hit 10 percent of images in 4 popular variants, the working set is about 10M x 0.1 x 4 x 60 KB = 240 GB, which fits comfortably in CDN caches. A resize with libvips of a 12 megapixel JPEG typically takes tens of milliseconds, paid once per variant per shield.

Cache key normalization

Turn /img/abc.jpg?width=611&q=83&fmt=auto into a canonical form: width snapped up to the nearest of 160, 320, 640, 960, 1280, 1920; quality to one of three presets; format resolved from Accept to avif, webp or jpeg; parameters sorted. The canonical string is the cache key, so equivalent requests share one cached object.

Trade-offs

ApproachStorageFirst-view latencyOperational risk
Pre-generate every variantHighestLowestBackfills needed when you add a size or format
On demand at the edgeLowestResize cost on first missCache-busting abuse if parameters are open
Hybrid: pre-generate the 2 or 3 hottest sizes, rest on demandModerateLow for common viewsTwo code paths to keep consistent
flowchart LR B["Browser"] --> E["CDN edge"] E -- "miss" --> S["Origin shield"] S -- "miss" --> R["Resize service"] R --> O["Original in object storage"] R --> S S --> E E --> B

How real systems do it

  • Cloudflare Image Resizing, imgix and Cloudinary expose URL-parameter transforms at the edge.
  • Thumbor is a widely used open-source resize server, and AWS publishes a Serverless Image Handler reference architecture using CloudFront, Lambda and Sharp.
  • Use Cache-Control with a long max-age on variants and version originals by key, so a replaced image gets a new URL instead of needing a purge.
Check yourself Question 1 of 3
Allowlist transform parameters recall
From: Edge Transformation Mechanics

An on-demand image service accepts any integer width in the URL. Why does the lesson insist on an allowlist of widths or signed transform URLs?

Key Takeaways

Avoid pre-generating hundreds of image sizes; resize dynamically on-the-fly at the CDN edge.
Serve modern compressed formats (WebP and AVIF) to slash bandwidth consumption by 30-50%.
Cache transformed assets at the CDN edge keyed by width, height, quality, and format.
Was this lesson helpful? Spot an issue or have a suggestion? Let us know on GitHub.
Report an issue