Learn
Netflix Open Connect: How Netflix Delivers Video to ISPs
Netflix Open Connect in 2026: The ISP-Embedded CDN Playbook A single Open Connect Appliance sitting in a regional ISP's ...
A catalog of 120,000 product photos served through the Cloudflare image CDN with six breakpoints and three format branches does not generate 720,000 billable transformations. It generates somewhere between 180,000 and 400,000, because format=auto collapses into a single billable unit per unique transformation and the AVIF/WebP split happens below the billing boundary. Most teams budget for the wrong number, then discover the real cost driver is variant sprawl in the cache, not the transformation line item. This article gives you the decision boundaries between Polish, Image Resizing and Cloudflare Images, 2026 pricing math, the cache-key mechanics behind variant explosion, a concrete AVIF fallback chain, and the volume threshold where a vendor-neutral edge gets materially cheaper.

Cloudflare ships three overlapping image capabilities and they are not interchangeable. Picking the wrong one is the most common architectural mistake teams make with the Cloudflare image CDN.
| Product | What it actually does | Billing model | Use when |
|---|---|---|---|
| Polish | Lossy or lossless recompression plus optional WebP conversion of the origin asset. No geometry change. | Included with Pro and above; no per-image charge | Legacy sites where you cannot touch markup and origin images are already correctly sized |
| Image Resizing (Transformations) | On-demand geometry, format and quality transforms against images you already host, via a resizing path prefix or a Worker binding | Per unique transformation, monthly counter | You own storage and origin, you want responsive srcset without a build step |
| Cloudflare Images | Storage plus delivery plus named variants. Upload API, signed URLs, direct creator upload | Per 100k images stored, per 100k images delivered | UGC pipelines, no existing object store, you want to delete the upload service |
Do not run Polish and Image Resizing on the same path. Polish operates on the cached origin object; resizing operates on the fetched source. Chaining them means you recompress an already-recompressed image, and the quality loss is visible in gradients and skin tones at any AVIF quality below 62. As of 2026 the practical guidance is: Polish for zones you will never modernise, Transformations for everything else. Polish also gives you no control over AVIF — it converts to WebP, full stop. If AVIF matters to your byte budget, Polish is not the tool.
The negotiation chain in 2026 resolves in this order: AVIF for clients advertising it in Accept, WebP for clients that advertise WebP but not AVIF, then the source format. Safari 16.4 and later advertise AVIF, so the old "Safari means WebP" heuristic is dead for anything but long-tail iOS versions. What remains true: any intermediary that strips or normalises the Accept header silently collapses you to JPEG. Corporate TLS-inspecting proxies do this. So do a surprising number of RSS readers and link-preview bots.
Instrument it. Sample production responses and bucket the Content-Type distribution by user agent family. If your AVIF share is below roughly 55 percent of image responses in 2026 traffic, something upstream is eating the header, or you have a client population that genuinely cannot decode AVIF.
| Format | Quality setting | Size vs JPEG q85 | Failure mode |
|---|---|---|---|
| AVIF | 60–68 | ~50–55% smaller | Above 72 the curve inverts and files grow past WebP |
| WebP | 75–80 | ~30% smaller | Chroma smearing on saturated reds below q70 |
| JPEG fallback | 82–85 | Baseline | Banding in hero gradients below q80 |
| AVIF, flat graphics | 50–58 | ~65% smaller | Text edges soften; use lossless PNG for UI chrome instead |
The one non-obvious result: AVIF loses to WebP on small images. Below roughly 200 by 200 pixels, AVIF container overhead plus the minimum tile structure often produces a larger file than WebP at equivalent perceptual quality. Thumbnails and avatars should be pinned to WebP explicitly rather than left to auto.
As of 2026, Cloudflare Image Transformations bill at roughly $0.50 per 1,000 unique transformations, with a free monthly allowance in the low thousands on paid plans. Cloudflare Images storage and delivery bill separately at roughly $5 per 100,000 images stored per month and $1 per 100,000 images delivered. These are the numbers to model against; check current rate cards before committing budget.
Here is the math that surprises people. A unique transformation is keyed on the full set of transform parameters plus the source URL. Because format=auto is one parameter value, the AVIF and WebP outputs of the same width share one billable transformation but occupy two cache entries. So:
Add a fifth parameter — say a fit mode or a gravity setting that varies per template — and the matrix multiplies again. This is the actual failure mode. Not price per unit, but combinatorial growth in the number of units.
Cache entries for resized images are keyed on the transform string. Every distinct permutation is a distinct object competing for edge cache residency. A catalog with 1.44 million variants against a finite edge cache means tail variants are evicted constantly, get re-transformed on the next request, and bill again. You pay twice: once for the transformation, once in latency.
Three rules that hold up in production as of 2026:
format=auto handles the common case. It does not handle the cases where Accept is unreliable, and those are the ones that generate support tickets. A defensible chain, in order of preference:
Verify with the cf-resized response header, which reports what the transform pipeline actually produced. Do not monitor cf-polished or cf-bgj; they describe a different code path and will mislead you.
On-demand transformation is the correct default up to a point. Past it, the economics invert. The threshold is roughly: 500,000 or more source images with five or more variants each, or any catalog where monthly transformation spend exceeds the cost of a pre-render pipeline plus object storage.
The alternative architecture: pre-render your variant matrix with libvips or sharp in a batch job, write the outputs to object storage with immutable cache headers and content-hashed paths, then serve through a CDN priced on bandwidth rather than per-operation. You lose on-demand flexibility. You gain deterministic cost, full control over encoder parameters, and the ability to run newer encoder builds than any managed service exposes.
This is where a bandwidth-priced edge does real work. BlazingCDN's volume pricing starts at $100/month for 25 TB — $5 per TB, or $0.004 per additional GB — and scales to $0.002 per GB at 2,000 TB. NVMe SSD edge storage matters for image workloads specifically, because a large pre-rendered variant matrix has a long tail that must be served from disk rather than memory. With 100% uptime and fault tolerance comparable to Amazon CloudFront at a materially lower cost per TB, it is a reasonable target for the delivery half of a pre-render pipeline.
To be fair about the competitive set: Bunny.net ships an integrated optimizer with per-request transform pricing that is genuinely convenient if you want to skip the batch job entirely. CDN77 and Gcore both have strong European footprints and their own transformation layers. If you want managed transforms with minimal engineering, those are real options. If you have already built the pre-render pipeline and what you need is cheap, fast, predictable delivery of a large static variant matrix, bandwidth-only pricing with one-hour onboarding wins on cost-per-TB math. Run both and compare invoices.
Format migrations fail quietly. Bytes go down, a subset of clients gets broken images, and nobody notices for a week because your synthetic monitoring only runs headless Chrome. Build this checklist into your release process.
Keep a pinned-format toggle in your image URL builder — one configuration value that switches format=auto to an explicit format across the whole site. Rolling back a format decision should not require a deploy. Purge by prefix rather than by individual URL; with a six-figure variant count, per-URL purge will not finish in a useful timeframe. Then re-warm your top 5,000 images by traffic before you declare the rollback complete, or your origin takes the full miss load.
No. When you use format=auto, the AVIF and WebP results of an otherwise identical transform count as one unique transformation for billing. They occupy separate cache entries, which affects hit ratio and eviction, but not the transformation counter. Explicitly requesting format=avif and format=webp as separate URLs does create two billable transformations.
Use Image Resizing for anything where you control the markup, because it gives you AVIF, explicit quality control, and geometry changes. Polish only recompresses and can convert to WebP, with no AVIF path and no width control. Never run both on the same asset path; the double compression is visible and the cost is real quality loss.
Four. 400, 800, 1200 and 1600 pixels covers the overwhelming majority of layouts, including 2x density displays which simply request the next candidate up. Six or eight breakpoints roughly halve per-variant cache hit rate for marginal byte savings, and they multiply your billable transformation count proportionally.
Two likely causes. Either the quality setting is above about 72, where AVIF's rate curve flattens and file size grows sharply, or the image is small — below roughly 200 by 200 pixels, AVIF container and tile overhead exceeds its compression advantage. Drop quality into the 60 to 68 range, and pin small assets to WebP explicitly.
Roughly 500,000 source images with five or more variants each, or any point where monthly transformation spend exceeds the amortised cost of a libvips batch pipeline plus object storage. Below that, on-demand is cheaper in engineering time. Above it, a pre-rendered matrix served through a bandwidth-priced CDN produces a flat, predictable bill.
Sample production responses and chart Content-Type by user agent family. A client population running modern Chrome that receives JPEG instead of AVIF is the signature. Corporate TLS-inspecting proxies are the usual culprit; the fix is markup-level picture element source ordering, which does not depend on Accept at all.
Pull your 200 highest-traffic images. Transform each one through your Cloudflare image CDN configuration at AVIF q64, WebP q78, and JPEG q84. Chart the size distribution and count how many images come out smaller as WebP than as AVIF. If that number exceeds 15 percent of your sample, your quality ladder is wrong or your catalog is dominated by small assets, and format=auto is costing you bytes rather than saving them.
Then multiply your source count by your width ladder by your format branches and look hard at the result. If the variant matrix is over a million entries, the interesting question is no longer which format to serve. It is whether an on-demand pipeline is the right architecture at all. What matrix size did you hit before your cache hit ratio started degrading? That threshold is the number worth comparing across teams.
Learn
Netflix Open Connect in 2026: The ISP-Embedded CDN Playbook A single Open Connect Appliance sitting in a regional ISP's ...
Learn
Google Cloud CDN Setup 2026: The Production Playbook The most expensive line in a Google Cloud CDN bill is rarely the ...