Skip to content
scroll to zoom · drag to pan

Formats, transparency and why not AVIF

Why format=auto is WebP — and why that is not a size argument

Section titled “Why format=auto is WebP — and why that is not a size argument”

This one has a history worth reading, because the first answer was wrong.

May 2026. A benchmark over 100 production samples concluded AVIF was 4.5–9.8% larger than WebP at equivalent quality. Case closed: keep WebP.

June 2026. Re-run, and the earlier result turned out to be a methodology artifact, not a property of the format. The original bench had:

  • encoded AVIF from an already-lossy lg.webp, not from the original, and
  • compared unmatched quality — AVIF at q70/effort4 against WebP at q80/effort6, where its own SSIM column showed the AVIF was higher quality.

Both biases pointed the same way. Re-run from originals at matched SSIM, AVIF is 14–20% smaller at every delivery size, and 25–43% smaller on flat interiors.

So AVIF wins on size, clearly. WebP is still the default, for two reasons that have nothing to do with bytes:

  1. Decode cost on low-end mobile. The device mix in Central America is not the device mix in a benchmark. AVIF decode is what a cheap phone feels.
  2. 3–6× encode time, on a synchronous, timeout-bounded request path. The first request for a new derivative pays that.

And the product context that makes the trade obvious: delivered file size is not the priority driver here — these clients have bandwidth. AVIF’s real 14–20% win buys something nobody is asking for, while its costs land squarely on mobile thermals and time-to-first-byte, which people do notice.

Decision: format=auto → WebP. AVIF only if you ask for it explicitly.

Worth revisiting if egress cost or a bandwidth-constrained market becomes a priority — at which point <picture> with AVIF on the large rungs is the path, not flipping the default.

Transparency: what survives and what does not

Section titled “Transparency: what survives and what does not”

JPEG has no alpha channel. That single fact drives all of this.

you upload you ask for you get alpha
PNG with alpha image/png PNG kept
PNG with alpha image/webp WebP kept (WebP has alpha)
PNG with alpha image/webp on WebKit JPEG fallback flattened onto white
PNG with alpha image/jpeg JPEG flattened onto white

Asking for PNG is a promise the compressor keeps. A request for image/png returns PNG and nothing else — no JPEG fallback, ever. That request means lossless or alpha, on purpose — icon extraction, sprite work, a cut-out — and silently handing back a flattened JPEG would be the same class of bug as the format mislabelling.

// A cut-out that must keep its transparency:
await nt.upload(file, {
presets: ["original", "thumb"],
compress: { mimeType: "image/png" }, // no fallback path exists
});

Without an explicit composite, transparent pixels encode as black — a cut-out product photo becomes a photo on a black background. The compressor composites onto white before any JPEG encode, so the failure mode is “lost transparency” rather than “ruined image”.

Two different goals, two different answers:

“I want the exact bytes back later.” → presets: ["original", …]. The original variant is the uploaded bytes, untouched, whatever they were.

“I do not want it re-encoded on the way up.” → that is the compressor’s convertSize threshold. The SDK’s defaults convert large PNGs to JPEG, because the alternative is what production actually looked like:

tenant twolink 20 files · image/png · avg 6.85 MB
tenant realtyone-cr 168 files · image/png · avg 13.16 MB (2 210 MB total)

Those are photographs saved as PNG. For a photo, PNG is the wrong container and converting is the right call. For a graphic with alpha, it is not — which is why asking for image/png explicitly disables the whole conversion path.

What iPhones actually produce. Decoded natively where the engine can — about 136 ms — and only falling back to a 341 kB WASM decoder where it cannot, which takes ~1,700 ms. Most users never fetch the decoder.

Delivery is always WebP by default, no matter what the client managed to encode. The server re-encodes every variant. The client format only affects upload size and the archived original — see Compression in the browser.