Should you compress images before your CDN re-en...

Should you compress images before your CDN re-encodes them? Measured through Next.js, wsrv.nl and Photon

By SJ
7 min read
Iminify blog cover on a blue gradient with a pixel pattern: "Should you compress before your CDN does?"
On this page

The Fjord, one of our five test photographs, is an 852,461-byte JPEG, the master every score below is measured against. Iminify's Smart level makes it a 568,598-byte JPEG. We sent both through Next.js 16.4.3's image optimizer at its default, WebP at quality 75. Next's WebP of the master weighed 321,790 bytes and scored 66.98 against the master on SSIMULACRA 2, where 100 means no difference from the master. Its WebP of the Smart file weighed 314,578 bytes and scored 64.30: 2.2 percent fewer bytes for 2.7 points.

Should you compress before a CDN or optimizer re-encodes your image? In our tests, on five JPEG photographs through Next and wsrv.nl, only losslessly. A lossless repack, which made our uploads 2.4 to 5.6 percent smaller, changed nothing in 80 of 80 Next responses. And in 40 of 40 comparisons at no more bytes, asking Next for a lower quality setting scored higher than the lossy first pass. If nothing re-encodes after you, compress first.

A lossless repack changed nothing Next or wsrv.nl sent

Iminify's Lossless level rewrites how a JPEG's coefficients are packed and leaves the pixels alone (25 files checked in an earlier post). On our five photographs it saved 2.4 to 5.6 percent of the master, and every file scored 100.00 against it.

Through Next, the five Lossless files produced the same bytes as the five masters: 80 of 80 responses had the same SHA-256. That is two runs of 40 requests, each for five photographs at two widths, as WebP 75 and JPEG 75 under Next's defaults and as WebP 75 and WebP 90 with qualities: [75, 90]. (JPEG is Next's answer to a browser that lists neither WebP nor AVIF.) wsrv.nl, a public image proxy, did the same, as JPEG and as WebP, on all five photographs.

At 1800 px and WebP 75, a Smart first pass trims 2 to 13 percent off what Next sends and costs 3 to 8 points

Next's default WebP 75, at the photographs' own 1800 pixels, each cell the median of the five photographs. Smart is Iminify's default level and Ultra its most aggressive:

Upload Upload size Delivered size Score against the master
Master 396,520 B 73,188 B 66.98
Lossless 383,500 B 73,188 B 66.98
Smart 128,292 B 67,964 B 61.27
Ultra 76,903 B 62,706 B 55.30

Per photograph, Smart's delivered file was 86.7 to 97.8 percent of the master's delivered file and scored 2.7 to 8.2 points lower. Ultra's was 82.2 to 92.8 percent and scored 8.1 to 14.5 lower.

Cloudflare's Polish compression page (updated 21 April 2026) says: "Re-encoding of files that are already optimized reduces their quality more than it reduces their file size." Next's second pass took 27 to 48 percent off the bytes of the Smart uploads and 8.6 to 22.2 points off their scores, which are different units.

Asking Next for a lower quality scored higher in all 40 comparisons

We asked Next for each master at twenty qualities from 50 to 90. For every lossy route (a Smart or Ultra upload and one Next setting) we took the highest of those qualities whose WebP of the master was no bigger than the route's file, and compared scores. Next's WebP of the master scored higher in all 40 comparisons (Smart or Ultra, delivered at WebP 75 or 90, two widths, five photographs), by 0.12 to 13.88 points, median 4.06.

On the Fjord, the Smart route's 314,578 bytes scored 64.30. Next's WebP of the master at quality 72 was 309,732 bytes and scored 65.55.

Scatter chart for the Fjord at 1800 px, score against bytes. The master through Next at twenty qualities runs from 243,122 bytes at 57.4 to 590,444 bytes at 83.1. The four lossy-first routes, Smart or Ultra then WebP 75 or 90, all sit below that curve, from 55.8 at 289,188 bytes to 77.3 at 562,868 bytes.

Median gain in points, by route At 1800 px At 1080 px
Smart, then WebP 75 +2.36 +0.93
Ultra, then WebP 75 +8.20 +2.55
Smart, then WebP 90 +5.46 +1.61
Ultra, then WebP 90 +12.33 +5.87

Next only serves the qualities in its qualities list, 75 by default. Listing a lower one is how you ask Next for fewer bytes.

The same comparison for wsrv.nl's WebP, on the ten Smart and Ultra uploads it covers, was won by the master's WebP in 10 of 10 cases, by 1.22 to 10.28 points. Its WebP of a master matched Next's byte for byte on each of the ten photograph and quality pairs those cases needed, so Next's sweep stands in for wsrv.nl's.

A second pass can hand you a file bigger than the one you uploaded

Delivered size as a percent of the upload, at 1800 px, over the five photographs:

Optimizer Smart upload Ultra upload
Next, WebP 90 99 to 152 (bigger on 4 of 5) 151 to 172 (5 of 5)
wsrv.nl, JPEG at its default quality 80 79 to 122 (bigger on 3 of 5) 115 to 133 (5 of 5)

Our WebP post found that a JPEG saved at 80 gives a bigger WebP from about quality 90.

What wsrv.nl and Photon did to the same files

wsrv.nl defaults to quality 80. Asked for WebP with output=webp, it delivered the Smart uploads at 75 to 97 percent of its WebP of the master and 3.6 to 8.8 points lower.

Photon, Jetpack's image CDN, answers a browser that lists WebP differently from one that doesn't. Asked for a JPEG, it returned the Lossless, Smart and Ultra files byte for byte (15 of 15) and the masters at 95.5 to 99.0 percent of their size, still scoring 100.00. Asked for WebP by a browser that lists it, as Chrome does, Photon matched wsrv.nl byte for byte on the five masters and the five Lossless files. For the lossy uploads it sent smaller files than wsrv.nl in nine of ten cases; the exception is the Fjord's Smart file. The Fjord's Ultra file came back as 231,974 bytes against wsrv.nl's 344,010, and scored 50.32 against 59.20. Photon's WebPs of the five Smart uploads weighed 38.5 to 97.1 percent of its WebP of the master and scored 3.6 to 23.0 points lower.

Cloudflare and Cloudinary: documented, not tested

Polish is not on the Free plan. Its compression page recommends origin JPEGs at quality 80 to 90, because blocky low-quality ones make bigger WebPs, and says "It does not make sense to apply lossy optimizations twice to images, because quality degradation will be larger than the savings in file size." We didn't run it: it needs a paid zone and a setting on a live site.

Cloudinary's q_auto documentation lists four presets and says nothing about sources that are already compressed. Its demo cloud answered fetches of six of our files with x-cld-error: ACL deny, so we sent none through it.

What to upload

  1. If something re-encodes after you, upload the master or its lossless repack and set the quality at the optimizer. Squarespace, for one, encodes its copies itself.
  2. If nothing does, compress first: Smart took the Fjord from 852,461 to 568,598 bytes, and Photon's JPEG path delivered it as it came. A browser that lists WebP gets Photon's second pass instead.
  3. To find out which one you have, fetch your image through your site and compare it with the file you uploaded, sending the Accept header a current browser sends. Photon answers it; wsrv.nl ignores it. Our check on wsrv.nl:
curl -sf -o upload.jpg https://www.iminify.com/image/showcase/photo-landscape/smart.jpg
curl -sf -o delivered.jpg -H 'Accept: image/avif,image/webp,image/*,*/*;q=0.8' 'https://wsrv.nl/?url=https://www.iminify.com/image/showcase/photo-landscape/smart.jpg'
wc -c upload.jpg delivered.jpg

Different sizes mean something rewrote the file: here 568,598 bytes became 449,828. A score against your original shows whether it lost quality.

How we measured

The photographs are the five JPEG masters of our corpus, 1800x1200, saved at quality 92, so every score says how far a file is from that JPEG, not from a camera original. The Lossless, Smart and Ultra files are Iminify's jpg output of each, the files its showcase serves; we re-ran all 15 through the API on 1 November 2026 and got identical SHA-256 on 15 of 15.

Next ran 16.4.3 in a container on sharp 0.35.5, a copy of the harness of our Next.js post: its answers for the five masters matched that post's outputs on 40 of 40 SHA-256, and a second run of all 160 requests (40 for each of the four uploads) returned identical bytes. Quality 90 came from qualities: [75, 90]. Next accepts at most twenty qualities, so the sweep used 50, 55, 58, 60, 62, 64, 66, 68, 70, 72, 74, 75, 76, 78, 80, 82, 84, 86, 88 and 90. We scored every answer with ssimulacra2 from libjxl v0.12.0 after decoding with djpeg or dwebp, against the master resized by sharp the way Next does, written losslessly. wsrv.nl and Photon answered curl requests on 1 November 2026 at the photographs' own size, and each file is scored against the master. We tested five photographs, WebP and JPEG, not AVIF.

Questions this post answers

Share this post

Share on X
Share on Facebook
Share on LinkedIn
Share on Reddit
Share on Hacker News
Email
Copy link
Link copied
Four teal circles on a transparent background, above the same image converted to JPG with Pillow, where the strips behind them came out magenta, white, black and black.

Why does a transparent PNG turn black as a JPG? The colour hiding underneath

We made an 800x400 test PNG with four strips that look alike: the same teal circle on a transparent background, four times over (the fourth with a soft shadow). Then we turned it into a JPG with Pillow, Python's imaging library, using its convert("RGB"). The four strips came back magenta, white, black and black. Nothing was added. Those colours were already in the PNG, sitting under the transparency. A JPG can't store transparency, so whatever writes it has to put something behind the picture. Some tools paint white. Some just reveal the colour stored under the transparent pixels, which is often black. And Chrome's canvas, the drawing surface web pages use to edit images, paints black whatever was there, because the HTML standard says it must. If you want white, or any other colour, you have to choose it before the JPG is written. Iminify's JPG output puts white behind the picture, and PNG to WebP keeps the transparency instead.

8 min read
Ten squares: 4 filled for tools that kept the IPTC AI tag at their defaults, 6 hollow for tools that dropped it, beside the title Does compression remove the AI tag?

Does compression remove the AI tag Merchant Center asks for? 10 tools, WordPress and Iminify tested

Google's Merchant Center help says: "Don't remove embedded metadata tags such as trainedAlgorithmicMedia from such images. All AI-generated images must contain the IPTC DigitalSourceType trainedAlgorithmicMedia tag." (Merchant Center's help page is dated February 2024; we read it on 26 October 2026.) So we put that tag on two AI images, a harbour scene from Nano Banana 2 (a JPEG) and a bakery illustration from the original Nano Banana (a PNG), ran them through 42 command-line runs and Iminify, added three larger JPEGs for a WordPress 7.1.3 site, and read the tag back with ExifTool each time. Each tool's default decides whether the tag survives, and neither lossy nor lossless predicts it. Of the ten tools in our table, four keep the tag at their defaults and six drop it, and for nine of them we found an option that flips that. Iminify, which is our product, lost it at every level that compresses: it survived in 6 of 51 uploads, and those six came back byte for byte unchanged. One ExifTool command puts the tag back for 514 to 568 bytes and, on the nine files we checked, leaves every pixel alone.

8 min read
Two cards for the same photograph: the JPEG saved at quality 80, 449 KB, score 75.6, and the WebP made from it at quality 90, 531 KB, score 71.3.

Why is my WebP bigger than the JPG? Measured on 40 JPEGs and 4 PNGs

One photograph of our corpus, the Fjord, saved as a JPEG at quality 80 weighed 449,258 bytes. Converted to WebP at quality 90, it weighed 531,474, which is 18% more. Scored against the corpus master it came from (a JPEG saved at quality 92), the bigger file was also the worse picture: 71.3 on SSIMULACRA 2, a score where higher means closer to the master, against 75.6 for the JPEG. Google's WebP FAQ says a WebP can grow larger than its source and names three situations. We measured each on five photographs and four graphics. A WebP comes out bigger when its quality is set too high for the JPEG it came from, when it is lossless, or when a PNG already squeezed to 256 colours goes to lossy WebP. A fourth cause, which the FAQ doesn't list, is that WebP isn't always smaller than a good JPEG even at the same score. Whichever it is, keep the smaller file when the two look alike.

7 min read

Try it on your own images

Drop a photograph in, pick Smart, and compare the result with the original before you download. Free, no account needed.