Worker Image CDN
A Cloudflare Worker that acts as an image CDN proxy. It fetches images from an origin server, automatically converts them to modern formats, resizes them on the fly, and caches the results in R2 for fast subsequent delivery.
It runs entirely on Cloudflare's edge - no servers to manage, no build step per image.
Why do I need this CDN?
Make your app faster
Images are typically the largest resource on a page and one of the biggest drivers of slow load times. That hurts user experience directly, and because Google uses Core Web Vitals (especially Largest Contentful Paint, which is usually an image) as a ranking signal, it hurts SEO too. Serving AVIF / WebP at the right dimensions from the edge cuts LCP dramatically.
Reduce bandwidth on both ends
Modern formats and on-the-fly resizing mean clients download a fraction of the bytes, and your origin stops re-serving the same oversized originals - transformed variants are cached in R2 and served from Cloudflare's edge.
It's free to run
The Worker and R2 bucket both sit comfortably inside Cloudflare's free tier for most small-to-medium sites, and R2 egress is free by default.
Free tier ceilings (at the time of writing): Workers allow 100,000 requests/day, and R2 gives you 10 GB of storage, 1 million Class A operations/month, and 10 million Class B operations/month. If you outgrow them, the Workers Paid plan ($5/month) raises request limits substantially, and R2 storage and operations continue on usage-based pricing. Check Workers pricing and R2 pricing for current numbers.
Features
| Feature | Description |
|---|---|
| Automatic format conversion | Serves AVIF or WebP based on the browser's Accept header |
| On-the-fly resizing | Resize via ?w= and ?h=, preserving aspect ratio and never upscaling |
| Quality control | Adjust output quality with ?quality=80 |
| R2 caching | Transformed images are stored in Cloudflare R2 and reused on subsequent requests |
| Step snapping | Dimensions and quality snap to configured steps, keeping the cache small and hit rates high |
| Cache observability | Every response carries an X-Cache: HIT/MISS header |
How it works
| Request | |
| ↓ | |
| Check R2 cache | |
| HIT ↙ | ↘ MISS |
| Serve cached image | Fetch from origin |
| ↓ | |
| Resize (if requested) | |
| ↓ | |
| Convert to AVIF / WebP | |
| ↓ | |
| Store in R2 | |
| ↓ | |
| Serve image | |