Image delivery
Self-hosted image optimization, without the egress bill
Hosted image services optimize your images well, then bill you per transformation, per stored asset, and per byte of egress. ModPageSpeed does the same work — transcode to WebP and AVIF, resize to the rendered size, target a perceptual-quality score — on the server you already run. Images never leave your origin, so there is nothing to meter on the way out.
The cost is structural, not a discount
The reason a hosted image pipeline has a bill that grows with traffic is architectural: the images live on someone else’s infrastructure, so every transformation and every byte served crosses a boundary that gets metered. When the optimizer runs inside the response path of the origin you already operate, that boundary doesn’t exist. There is no upload, no external fetch on a cache miss, and no per-image fee — the work is part of serving the page.
| Dimension | Hosted image service | Self-hosted (ModPageSpeed) |
|---|---|---|
| Where images are stored and processed | On the vendor’s infrastructure; originals are uploaded or fetched out | On your own origin; bytes never leave the server |
| Billing model | Per transformation, per stored asset, and per byte of egress | A per-site license; no per-image, per-transform, or egress metering |
| Round-trip on a cache miss | Origin → vendor → CDN → user, with egress on each external hop | Optimization happens in-place; no external round-trip to bill |
| Data residency | Image data transits a third party | Image data stays inside your stack |
This is the same trade hosted services make against running your own server. ModPageSpeed is a self-hosted optimizer, in the same category as imgproxy and Thumbor, with one difference: it sits in the response path of the site you already serve, so you don’t rewrite image URLs to point at a separate image server.
What it does to each image
ModPageSpeed transcodes JPEG/PNG/GIF to WebP (and AVIF on 2.0), recompresses with quality-aware encoders, resizes to the rendered display size, and strips EXIF/ICC metadata. Typical result: 40–70% smaller images at visually equivalent quality.
Transcode
JPEG, PNG, and GIF are transcoded to WebP and AVIF when the browser advertises support, with the original kept as a fallback. Supported formats: WebP, AVIF, SVG.
Resize
Each image is resized to the dimensions it is actually displayed at, so a phone
doesn’t download a desktop-sized hero. ModPageSpeed 2.0 generates viewport-tagged
variants instead of shipping one large image with a srcset.
Target quality
A learned quality model picks the encoder setting that hits a target SSIMULACRA2 score — a perceptual metric — per image, instead of one global quality number applied to everything. It runs on CPU; no GPU.
Up to 37 variants per image, served by capability
ModPageSpeed 2.0 doesn’t produce one optimized file per image — it produces a set of variants and serves the one that matches the requesting browser. The raster variants multiply out from four axes; an SVG variant for eligible images brings the ceiling to 37.
| Axis | Values | Count |
|---|---|---|
| Format | WebP, AVIF, original | 3 |
| Viewport class | Mobile, Tablet, Desktop | 3 |
| Pixel density | 1×, 2× | 2 |
| Save-Data | on, off | 2 |
| Raster variants | 3 × 3 × 2 × 2 | 36 |
| + SVG for eligible images | total per image | 37 |
Variants are generated lazily, once, and cached — the cache stores them as alternates of a single key and the request path selects the best match. A browser that only takes WebP on a 1× mobile screen never causes the AVIF or 2× variants to be served, but they are there when a different client needs them. In ModPageSpeed 2.0 the encode runs in a separate worker process out of the request path, so the first request for an image is served as the original while the worker optimizes in the background; later requests get the cached variant.
Turning it on
Image transcoding, resizing, and recompression are on as soon as the module is enabled — there is no per-filter list to assemble. On nginx, ModPageSpeed 2.0 is two directives:
# nginx — ModPageSpeed 2.0
pagespeed on;
pagespeed_cache_path /var/lib/pagespeed/cache.vol;
That is the whole image pipeline: the worker reads originals from the cache, generates the
variants, and writes them back; the nginx module serves the matching variant from the
memory-mapped cache. To turn image work off you set a worker flag (--disable-image), not on.
For .NET, the same engine ships as ASP.NET Core middleware — one package, native worker bundled, no separate image server to deploy:
# ASP.NET Core — ModPageSpeed 2.0 middleware
dotnet add package WeAmp.PageSpeed.AspNetCore See the getting-started guide for the nginx setup and ASP.NET configuration for the middleware. The mod_pagespeed 1.15 line offers the same WebP image filters as a native module (AVIF and the learned-quality model are 2.0-only); its prebuilt, signed packages cover Debian 11 bullseye (nginx 1.18.0), Debian 12 bookworm (nginx 1.22.1), Debian 13 trixie (nginx 1.26.3), Ubuntu 22.04 jammy (nginx 1.18.0), Ubuntu 24.04 noble (nginx 1.24.0) for amd64 + arm64 via packages.modpagespeed.com.
See it on a real image
Each filter has a before/after example with the actual bytes. The image filters are the ones that do most of the work on a typical page:
- rewrite_images — transcode and recompress an image, with the before/after byte sizes
- responsive_images — generate resolution variants for a single
<img> - resize_rendered_image_dimensions — resize to the size the page actually renders the image at
- lazyload_images — keep below-the-fold images off the critical path
The live demo runs a real site through the pipeline and shows the page-weight delta, and the savings calculator estimates the byte reduction for your own traffic.
Self-hosted image optimization: common questions
- Can I optimize images without a CDN or an image service?
- Yes. ModPageSpeed runs the optimization on your own server — as an nginx module, behind an nginx reverse proxy, or as ASP.NET Core middleware. It transcodes to WebP and AVIF, resizes to the rendered size, and serves the result from a local cache. There is no upload step, no external service, and no per-image fee, because the work happens in your stack.
- How is this different from Cloudinary, imgproxy, or Thumbor?
- Cloudinary is a hosted service billed per transformation, per stored asset, and per byte of egress. imgproxy and Thumbor are self-hosted services you run as a separate image server and call by rewriting your image URLs to point at them. ModPageSpeed sits in the response path of the site you already serve, optimizes the images the page references without URL rewriting on your part, and caches the variants — so it is self-hosted like imgproxy and Thumbor, but with nothing to wire into your markup.
- Does self-hosting image optimization cost more in CPU?
- Optimization runs once per image variant and the result is cached, so steady-state cost is a cache read, not a re-encode. In ModPageSpeed 2.0 the encode happens in a separate worker process out of the request path, so a slow or heavy transcode cannot stall the web server — the first request for an image is served as the original and the optimized variant appears on later requests. The quality model used to pick encoder settings runs on CPU — no GPU is required.
- What image formats and sizes does it generate?
- It transcodes to WebP and AVIF (and keeps the original as a fallback), and resizes each image to the size it is actually displayed at. ModPageSpeed 2.0 generates up to 37 variants per image — 36 raster variants across format, viewport class, pixel density, and Save-Data, plus an SVG variant for eligible images — and serves the right one based on what the requesting browser advertises.
- How much smaller are the images?
- Typical result is 40–70% smaller images at visually equivalent quality, from format transcoding (WebP/AVIF) plus quality-aware recompression and resizing to the rendered dimensions. The exact figure depends on the source images; pages dominated by already-optimized assets see less.
- How does it decide the compression quality?
- You can set fixed quality per format. By default, ModPageSpeed 2.0 uses a learned quality model that predicts the encoder setting needed to hit a target SSIMULACRA2 score — a perceptual metric that tracks how different two images look to a person — so it compresses as far as it can without a visible difference, per image, instead of applying one global quality number to everything.
- Do my images leave my server?
- No. The originals stay on your origin, the optimization runs locally, and the variants are written to a local cache. Nothing is uploaded to a third party and there is no external egress on the optimization round-trip.
Run it on your own images
Download ModPageSpeed and point it at your origin — it optimizes immediately, licensed or not. Production use requires a commercial license — but the software never locks you out.
Licensed per site, not per image or per byte — see the pricing ladder.
See also:
- The economics of image optimization — where the per-transform and egress costs actually come from
- Self-hosted image optimization, in depth — the longer write-up behind this page
- The nginx image-optimization module — how the pipeline fits into an nginx server
- Image optimization in ASP.NET Core — the same engine as .NET middleware
- ModPageSpeed vs Cloudinary · vs imgproxy · vs Thumbor
- ModPageSpeed 2.0 features — image transcoding, critical CSS, minification, and variant-aware caching
Cloudinary, imgproxy, Thumbor, and other product names are trademarks of their respective owners. Comparisons reflect publicly available information as of 2026 and describe architectural differences for evaluation; We-Amp B.V. is not affiliated with or endorsed by any of them.