Optimize images for websites and mobile apps
Resize and convert the images on your origin on request with Image Processor, cache every variant, and request a fixed set of sizes from your pages.
A commerce, media, or marketing team keeps a large image library on its own origin or CMS, and pages that load full-size images are slow on mobile networks. Every device needs the same picture at a different size, and producing and storing each size in advance does not scale with the library. This page configures an application that resizes and converts each image on request from the original on the origin, caches every variant it produces, and has the pages ask for a small, fixed set of sizes. The result is measured by the image bytes delivered compared with the originals, and by the share of image requests answered from cache.
This use case does not cover video or image editing workflows.
Prerequisites
- An application that serves your images from your origin through a connector and a workload. To create them, refer to Applications quickstart.
- Image Processor and Application Accelerator on that application. Image Processor transforms the images, and Application Accelerator owns the query-string variation that caches each transformation separately. To turn both on, refer to Image Processor quickstart.
- A personal token, for the API steps. To create one, refer to Personal tokens.
- Access to the templates that render the
imgelements of your pages. - The paths and sizes of your images. This page uses
/images/for the image path on the origin,www.example.comfor the domain, and three display widths of400,800, and1200pixels. Replace each value with yours in every step.
Required products
| The pages need | Which means | Product | Documented in |
|---|---|---|---|
| Each image at the size and format the page asks for, from one original | A rule with Optimize Images on the image path, and an ims query string in each image URL | Image Processor | Configure Image Processor on an application and Image Processor URL parameters |
| Each variant served from cache after its first request | A cache setting that varies the cache key by the ims argument | Cache | Image delivery |
A cache key per ims value | Cache vary by Query String, with ims in an allowlist | Application Accelerator | Configure Advanced Cache Key for an application |
| Bytes saved and image requests served | The Bandwidth Saving dashboard and the Image Processor tab, filtered to the domain | Real-Time Metrics | Build dashboards |
Reference architecture
This page builds the Origin-backed image optimization proxy: image routes on an application that transform the originals fetched from your origin and cache each variant.
Read the diagram from the image rule. The rule on the image path sends the request to Cache first, and a variant already stored answers it with no processing and no origin request. Only a miss reaches Image Processor, which fetches the original through the connector, transforms it, and stores the result for the next request of the same variant. The origin stays in the path of every miss.
Dataflow
- A page requests an image under
/images/with animsquery string that names the size, such as?ims=fit-in/800x800/filters:quality(85). - The application’s rule on
/images/applies theimagescache setting, whose cache key varies byims, and the Optimize Images behavior. - A variant already in cache answers the request without processing, and a variant served from cache is not counted against the Images meter.
- On a miss, the application fetches the original from your origin through the connector, so the origin’s availability and egress stay in the data flow of every miss.
- Image Processor resizes the original and converts it to WEBP for browsers that accept that format. It never modifies the original, and it does not keep the variant as an asset of the account.
- Cache stores the variant under a key that carries the
imsvalue and, for a converted image, the delivered format. The next request for the same size and format is answered from cache, and the origin serves an original only on a miss.
Components
- application: the Platform Resource that holds the image route, the
images - optimizerule that matches/images/and applies theimagescache setting and Optimize Images. - Image Processor: transforms the original into the variant the
imsquery string asks for, and chooses WEBP for browsers that accept it. - connector: the Platform Resource that reaches the origin of the originals on each cache miss.
- Cache: stores each variant under its own key. The key varies by
imsthrough the query-string allowlist of the cache setting, which belongs to Application Accelerator. - Real-Time Metrics: shows the bytes Image Processor saved, the image requests served, and the share answered from cache.
Other designs for this use case
- Object storage-backed image optimization proxy: for teams that move their originals to Azion, such as user uploads or a product catalog. The originals live in Object Storage, uploaded with the Azion CLI or the S3-compatible API, so the design adds an upload path and the request flow has no customer origin.
Configure the cache setting for image variants
The images cache setting gives each ims value its own cache key, so a request for the 400-pixel image is never answered with the 800-pixel one. Cache vary by Query String uses an Allowlist with only ims, so another argument, such as a campaign tag, does not create another copy of the same image.
Max Age is 31536000 seconds, the ceiling a cache setting accepts. A variant served from cache runs no transformation and adds nothing to the monthly Images meter, while a short Max Age repeats the same transformation on a timer that has nothing to do with changes at the origin. The browser cache honors the Cache-Control your origin sends for each image.
Create the cache setting as Configure Advanced Cache Key for an application describes, with these values. The rule that applies it is the next section.
- Name:
images. - Browser Cache: Honor cache policies.
- Cache: Override cache behavior, with Max Age set to
31536000. - Cache vary by Query String: Allowlist, with
imsas the only argument.
The application has a cache setting that stores one object per distinct ims value, for up to a year.
Configure the image rule
The image rule matches every request under /images/, applies the images cache setting, and adds Optimize Images, which hands the request to Image Processor. A request the rule does not match is delivered unprocessed, so the rule is what gives the ims query string its meaning.
The rule adds no Accept header. Image Processor detects whether the browser supports WEBP from the browser’s own Accept header and converts the image when it does, so each browser receives a format it reads. Forcing Accept: image/webp would send WEBP to browsers that never asked for it.
Create the rule as Configure Image Processor on an application describes, with these values in place of the guide’s extension match:
- Name:
images - optimize, in the Request Phase. - Criteria:
${uri}starts with/images/. - Behaviors: Set Cache Policy with the
imagescache setting, then Optimize Images. No Add Request Header behavior.
Through the API, the rule carries this criterion and both behaviors, and optimize_images takes no attributes:
Every request under /images/ now reaches Image Processor and carries the images cache setting. A new rule takes a few minutes to propagate.
Configure the image URLs in your pages
Each distinct ims string is a distinct object in cache, and a distinct transformation on its first request. A page that asks for any width the layout happens to compute stores an object per width, while a page that asks for three fixed widths stores three. The templates therefore request 400, 800, and 1200 pixels only.
Each URL uses fit-in, which keeps the image’s proportions inside the box and never enlarges it, so no part of a product photo is cropped. Each URL also applies quality(85), the value Azion recommends, which optimizes the file without a noticeable loss of visual quality. The 1,200-pixel box stays under the default width limit of 3,840 pixels.
In the template that renders an image, write the three sizes in the srcset of the img element, so the browser picks the smallest one that fits:
Keep ims as the last argument of the query string. A parameter placed after it may make the request return a 504 error, so a script that appends a cache-busting or tracking value inserts it before ims.
Pages built from the template request one of three variants of each image, and each variant is processed once and then served from cache.
Verify the setup
-
The image is processed. Request one size of an image with a browser’s
Acceptheader:The response carries
x-ims: Enabled,content-type: image/webp, andx-original-image-sizewith the size of the original before the transformation. -
Each variant answers from cache. Request the same URL twice with the
Pragma: azion-debug-cacheheader:The second response carries
x-cache: HIT, andx-cache-keyends with theimsvalue and@@webp, the format the variant was converted to. -
Two sizes are two objects. Request the
400x400URL with the same headers. Itsx-cache-keydiffers from the800x800key, and its first response carriesx-cache: MISS. -
A browser without WEBP gets the original format. Request the
800x800URL with-H "Accept: image/jpeg"and thePragma: azion-debug-cacheheader. The response carries the original format incontent-type, and itsx-cache-keycarries no@@webp.
For how to read the debug headers, refer to Check the cache status of a response.
Measuring results
| Metric | Where to read it | What working looks like |
|---|---|---|
| Image bytes saved compared with the originals | The Bandwidth Saving dashboard of Real-Time Metrics, filtered to the host, or bandwidthImagesProcessedSavedData in the workloadMetrics dataset. Refer to Build dashboards | Grows with the image traffic once the templates request the three sizes |
| Image requests served | The Image Processor tab of Real-Time Metrics, Total Requests | Follows the image traffic of the pages built from the templates |
| Share of image requests answered from cache | Requests Offloaded on the Requests dashboard, filtered to the host. Refer to Measure cache offload for a domain | Rises as each variant is cached, because each one is processed once and served from cache after |
Best practices
- Request a small, fixed set of sizes. Every distinct
imsstring is a distinct object in cache and a distinct transformation counted against the Images meter. Three widths per image cost three transformations, however many visitors load them. - Purge every variant when an original is replaced. A replaced original leaves its variants cached for up to a year, one key per size and per format. A URL purge does not reach the
@@webpvariants, so purge them with a wildcard that ends the path with*, such aswww.example.com/images/blue-shirt*. For the wildcard purge and its daily bound, refer to Purge pages when the origin publishes a change. - Keep
imsthe only argument in the allowlist. An allowlist that names onlyimskeeps every other argument out of the cache key, so tracking values do not multiply the variants. For why, refer to Applications best practices. - Use fit-in when no edge may be lost.
?ims=800x800fills the box exactly and autocrops the axis that overflows.fit-inkeeps the whole image inside the box, so use the plain form only where the layout needs the box filled.