Image bills grow in two places: what you pay a service to transform images, and what you pay to deliver bytes nobody needed. Both are usually two-thirds waste. Here is where the money actually goes and what to cut first.
Managed image services bill on transformations or on unique derivatives stored. A responsive srcset with eight widths, times three formats, times two DPRs is 48 derivatives per source image — and analytics almost always show that four or five of them serve 95% of requests. Fix the widths to a short ladder (say 400, 800, 1200, 1600), cap DPR at 2, and serve AVIF with a WebP fallback rather than all three formats. That alone typically cuts derivative count by two-thirds, and derivative count is the billed unit.
If your images are known at deploy time — product photos, blog headers, marketing pages — you do not need a transformation service at all. A sharp script in your build produces every size once, and the CDN serves them as static files at storage prices instead of compute prices. Reserve on-the-fly transformation for genuinely user-uploaded content where you cannot enumerate the inputs.
cwebp -q 80 in.png -o out.webp — quality 80 is the usual sweet spot for photosavifenc -s 6 --min 20 --max 40 in.png out.avif — AVIF is typically noticeably smaller than WebP at matched quality, at the cost of much slower encodingoxipng -o4 --strip safe in.png — lossless PNG, good for flat graphics and screenshotsjpegoptim --max=82 --strip-all *.jpg — in-place JPEG re-encode with metadata removedsvgo --multipass icon.svg — for anything vector, which should not be a raster image at allWrap these in a build step and the recurring cost drops to zero. Encoding time is a one-off you pay in CI, not per request.
Content-hash your filenames and serve them with Cache-Control: public, max-age=31536000, immutable. Every re-download you prevent is bandwidth you do not buy. The common mistake is a short max-age on images that never change, which turns a one-time transfer into a monthly one for every returning visitor.
Add loading="lazy" to everything below the fold and fetchpriority="high" to the single LCP image. Set explicit width and height so the browser reserves space and you do not pay for layout shift in ranking terms as well as bytes. And check the actual rendered size of your largest images — serving a 2400px original into a 600px slot is the most common single line item on an image bill.
User-generated uploads at unpredictable dimensions, automatic format negotiation via Accept, face-aware cropping, and video thumbnails. If you are doing those things, a transformation service is cheaper than building it. If you are serving 200 known marketing images, you are renting a factory to make four objects.