Cloudflare Image CDN: WebP, AVIF and Resizing Best Practices

Cloudflare Image CDN in 2026: WebP, AVIF and Resizing Playbook

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.

image-2

Cloudflare image CDN in 2026: three products, one confusing surface

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.

ProductWhat it actually doesBilling modelUse when
PolishLossy or lossless recompression plus optional WebP conversion of the origin asset. No geometry change.Included with Pro and above; no per-image chargeLegacy 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 bindingPer unique transformation, monthly counterYou own storage and origin, you want responsive srcset without a build step
Cloudflare ImagesStorage plus delivery plus named variants. Upload API, signed URLs, direct creator uploadPer 100k images stored, per 100k images deliveredUGC pipelines, no existing object store, you want to delete the upload service

The Polish question, settled

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.

WebP and AVIF on Cloudflare: what format=auto actually negotiates

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.

Quality ladder, 2026 measurements

FormatQuality settingSize vs JPEG q85Failure mode
AVIF60–68~50–55% smallerAbove 72 the curve inverts and files grow past WebP
WebP75–80~30% smallerChroma smearing on saturated reds below q70
JPEG fallback82–85BaselineBanding in hero gradients below q80
AVIF, flat graphics50–58~65% smallerText 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.

Cloudflare Images pricing and the transformation cost model

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:

  • 10,000 images, 4 widths: 40,000 transformations. About $20 per month, plus egress.
  • 120,000 images, 6 widths: 720,000 potential transformations — but only the ones actually requested bill. Long-tail catalogs typically see 25–40 percent of the variant matrix hit in a given month. Realistic: 180,000 to 288,000 transformations, roughly $90 to $144.
  • Same catalog, DPR variants added (1x and 2x): the matrix doubles to 1.44 million. Now you are looking at $180 to $290 per month in transformation fees alone.

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.

The variant sprawl rule

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:

  • Cap your width ladder at four values. 400, 800, 1200, 1600 covers almost every layout. Adding 600 and 1000 roughly halves your per-variant hit rate for maybe two percent byte savings.
  • Do not encode DPR as a separate transform. Let the width ladder plus an accurate sizes attribute handle density. A 2x display at 400 CSS pixels requests the 800w candidate, which you already have.
  • Normalise transform parameter order and casing at the edge before the transform executes. Two functionally identical URLs with parameters in different order are two cache entries and two billable transformations.

The AVIF fallback chain for clients that cannot decode it

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:

  1. Accept-based negotiation at the edge. Primary path. Vary on Accept so caches do not cross-contaminate.
  2. Explicit picture element source ordering in markup. Ship an AVIF source, a WebP source, and an img fallback with an explicit format parameter on each. The browser decides, not the header. This survives header-stripping proxies entirely.
  3. Client hints where available. Sec-CH-DPR and Sec-CH-Width let you drop DPR transforms from the URL space, shrinking the variant matrix.
  4. Pinned JPEG for known-bad user agent families. Maintain a short list of link-preview bots and email clients that mis-advertise support. Serve them a single pinned JPEG variant. This is uglier than it should be and it is still the right call.

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.

Where a vendor-neutral image edge gets cheaper at volume

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.

Diagnostics and rollback: what to check before and after a format change

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.

Pre-deploy verification

  • Replay 50 representative source images through the transform pipeline with Accept headers pinned to AVIF-only, WebP-only, and JPEG-only. Confirm Content-Type matches in all three branches.
  • Compare AVIF and WebP output sizes per image. Flag any image where AVIF is larger. Those are usually small graphics or images with heavy fine detail; pin them to WebP.
  • Check that Vary includes Accept on every transformed response. A missing Vary here poisons shared caches and serves AVIF to clients that cannot render it.
  • Measure the variant matrix size: source count times width count times format branches. If it exceeds one million, reduce the ladder before shipping.

Post-deploy monitoring

  • Content-Type distribution by user agent family, sampled hourly. A sudden JPEG spike means a proxy started stripping Accept.
  • Transformation count against your monthly budget, checked daily for the first week. Unexpected growth means a template is generating unbounded parameter permutations.
  • Edge cache hit ratio for image paths specifically, separated from HTML and static assets. A drop below 85 percent on a stable catalog indicates variant sprawl.
  • LCP by device class in field data. Chrome and Safari separately. Byte savings that do not move LCP mean your bottleneck is elsewhere.

Rollback procedure

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.

FAQ

Does the Cloudflare image CDN charge separately for AVIF and WebP outputs of the same image?

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.

Should I use Polish or Image Resizing on the Cloudflare image CDN?

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.

How many responsive width breakpoints should I generate?

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.

Why is my AVIF file larger than the WebP version?

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.

At what catalog size does pre-rendering beat on-demand transformation?

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.

How do I detect that a proxy is stripping the Accept header?

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.

Run this benchmark this week

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.