Category: Performance & Caching

Cache design, image formats, variant control, measurement, and delivery performance.

  • How to measure image payload waste

    How to measure image payload waste

    Short answer: For each image, compare its rendered CSS size and device-pixel ratio with the selected resource’s intrinsic dimensions, then examine transferred bytes, format, quality, and cache status. Aggregate the excess by component and page template so fixes target systems, not isolated files.

    An image can be wasteful in several ways. It may contain far more pixels than the slot needs, use an inefficient format, carry unnecessarily high quality, include unneeded metadata, or miss the cache. One number cannot diagnose all of them.

    What should you capture in the browser?

    Record the page URL, image element or component role, rendered width and height, device-pixel ratio, currentSrc, intrinsic width and height, encoded content length, transferred bytes, content type, loading priority, and timing. Also capture whether the image was the LCP element.

    The selected resource’s intrinsic dimensions can be compared with rendered dimensions multiplied by DPR. If a 400 CSS-pixel slot on a 2x device receives a 1600-pixel-wide file, the dimensional ratio is 2 relative to the 800-pixel physical need. That does not translate directly into twice the bytes because content and encoding matter, but it identifies a sizing problem.

    MDN documents currentSrc, naturalWidth, and related properties on HTMLImageElement. Browser performance APIs and developer tools can provide timing and transfer information, subject to cross-origin timing permissions.

    How do you estimate avoidable bytes?

    The most reliable method is to generate an appropriate comparison derivative for the actual slot, using the same crop, format, and quality policy. Compare its encoded size with the selected response. The difference is a concrete opportunity rather than a geometric guess.

    At scale, you can approximate dimensional waste from area ratio and flag large outliers for exact regeneration. Do not claim that halving width always quarters transfer size; image entropy, format headers, encoder settings, and responsive crop all affect the result.

    Separate cache transfer from representation size. A browser memory-cache hit may transfer zero bytes but the underlying resource can still be oversized for first-time visitors. Record encoded object bytes as well as observed network transfer.

    Which root causes should reports distinguish?

    Classify oversize selection, missing responsive candidates, inaccurate sizes, source upscaling, format fallback, excessive quality, cache miss, and duplicate request. Each maps to a different owner and fix.

    Oversize selection often points to the sizes attribute or a sparse width ladder. Too many near-identical variants points to variant explosion, not insufficient candidates. A heavy correctly sized image may need format or quality work.

    Duplicate requests can come from a preload that does not match final markup, a URL mutation during hydration, or two visually overlapping elements. A waterfall view is more informative than a byte inventory in that case.

    Lab audit or field measurement?

    Use both. Lab runs provide detailed, repeatable traces across chosen viewports, DPRs, and network conditions. They make it easy to inspect markup and test a candidate fix. Field data reveals the actual distribution of layouts, devices, routes, and cache states.

    Google’s Lighthouse documentation describes its properly size images audit, which is a useful diagnostic starting point. Do not stop at the score; trace flagged resources back to the component and delivery policy.

    In field monitoring, sample image observations to control volume. Aggregate by stable component name and preset, not by full signed URL. Full URLs can have high cardinality and may contain sensitive tokens.

    How do you prioritize fixes?

    Estimate total impact as avoidable bytes per view multiplied by affected page views, then consider whether the image is render-critical. A moderate saving on the LCP image may be more valuable than a larger saving far below the fold. Also prioritize systemic fixes that improve many assets.

    Start with wrong sizes, missing candidates, and unconstrained sources. Then review format and quality. Finally address smaller metadata opportunities. This order tends to deliver meaningful savings without lowering visible quality.

    Segment by mobile and desktop. An average can hide a mobile layout that routinely downloads desktop candidates. Review upper percentiles and top offending templates, not only the global mean.

    How do you prove the fix worked?

    Repeat the same lab scenarios and compare selected URLs, intrinsic dimensions, bytes, and timings. Confirm that visual quality and layout stability remain acceptable. Then watch field distributions after rollout.

    Use versioned transformation URLs so old cached objects do not contaminate the comparison. Track cache hit ratio and cold-transform rate; a new policy that saves bytes but creates many one-off derivatives may shift cost elsewhere.

    Image payload waste becomes manageable when it is described as a chain of evidence: slot, selected candidate, representation, transfer, and page role. That evidence points directly to the responsible component, markup rule, or image policy.

  • AVIF vs WebP vs JPEG: a delivery decision

    AVIF vs WebP vs JPEG: a delivery decision

    Short answer: Keep JPEG as a dependable photographic fallback, add WebP for broad modern efficiency, and consider AVIF when your corpus shows worthwhile savings at acceptable visual quality and processing cost. Negotiate or declare formats through a cache-safe delivery policy.

    No format wins every image. A codec that compresses photographs extremely well may perform differently on illustrations, screenshots, gradients, transparency, or tiny thumbnails. The right decision is a tested policy, not a single benchmark copied from another site.

    What differs between the formats?

    JPEG is mature, universally supported for photographic delivery, quick to encode, and well understood. It does not support alpha transparency and can show blocking or ringing at aggressive settings. Progressive JPEG can improve perceived loading in some contexts.

    WebP supports lossy and lossless modes, transparency, and animation. Browser support is broad, and many image platforms provide efficient WebP output. It is a practical modern default for mixed web content when a compatible fallback exists.

    AVIF supports advanced compression, alpha, and high dynamic range capabilities. It can produce smaller photographic files at comparable perceived quality, but encode cost and artifact behavior vary by content and settings. Support must be considered for the browsers, webviews, crawlers, and downstream tools your application actually serves.

    MDN maintains current compatibility and format characteristics in its image file type guide. Use that as a living reference rather than relying on old support assumptions.

    How should you compare quality?

    Do not compare quality numbers across formats. A value of 70 is not a portable visual target between JPEG, WebP, AVIF, or different encoders. Generate candidates at several settings, then compare both visual output and size.

    Build a corpus with portraits, landscapes, products, dark scenes, fine texture, gradients, screenshots, illustrations, transparency, and text within images. Test the real delivery dimensions because resizing can change which artifacts are visible.

    Use perceptual metrics as screening tools, then visually review business-critical classes at rendered size. Watch for smearing, edge halos, color shifts, banding, loss of fine text, and slow decode on constrained devices. The guide to automatic quality describes how to operationalize these thresholds.

    Explicit format or content negotiation?

    With explicit format URLs, markup or application logic requests .avif, .webp, or .jpg. A <picture> stack can give the browser ordered choices. The URLs are easy to reason about and cache independently, but candidate markup can become large when mixed with art direction and many widths.

    With automatic negotiation, one visible URL returns a supported format based on request capabilities. This simplifies markup but makes cache configuration critical. The response must vary safely so an AVIF-capable client’s object is not served to an incompatible client.

    Cloudinary describes automatic format selection in its image optimization documentation. Cloudflare documents format behavior in its image transformation options. Verify the exact provider and CDN interaction through requests, not only configuration screens.

    Does the smallest file always improve performance?

    Transfer size matters, especially on slow connections, but it is one part of the path. A format can cost more to encode on the cold transformation path, take more CPU to decode, or delay availability if generated on demand. A slightly larger warm object may outperform a smaller derivative that is constantly regenerated because of a fragmented key.

    Measure time to first byte, transfer duration, decode impact where available, and the page’s user-facing metrics. For an LCP hero, early discovery and correct dimensions can have more impact than a modest codec difference. The LCP image guide helps prioritize those factors.

    What fallback policy is robust?

    Always retain a broadly compatible representation for clients and integrations that cannot consume the preferred format. Confirm that social card fetchers, email clients, PDF generators, native webviews, and third-party consumers do not depend on a format they fail to decode.

    If automatic negotiation fails or the preferred encode errors, define whether the service falls back to another format or returns an error. Silent fallback is resilient but should be observable through Content-Type and metrics.

    Preserve PNG or another lossless path where transparency, sharp interface graphics, or archival requirements justify it. This comparison is focused on photographic delivery, not a rule to convert every file.

    How do you ship the policy?

    Create a versioned format preset and roll it out by asset class or page cohort. Record output content type, bytes, transform latency, cache hit ratio, and visual review results. Use the payload waste measurement guide to compare selected resources in real layouts.

    Keep rollback simple through versioned URLs or a policy flag. Re-run the corpus when encoders, provider behavior, browser mix, or content mix changes.

    The best format policy is conditional and measurable: known fallback, modern alternatives where they help, correct cache variation, and quality thresholds derived from the images your users actually see.

  • Prevent image variant explosion

    Prevent image variant explosion

    Short answer: Restrict transformations to an approved vocabulary, snap dimensions to a shared ladder, canonicalize equivalent requests, and require signatures for expensive or uncommon operations. Monitor unique variants per asset so a mistake is visible before it becomes a cost problem.

    On-demand image processing is powerful because a caller can ask for exactly what a layout needs. It becomes dangerous when every pixel value, crop, quality number, and query ordering creates a new stored derivative and a cold encode.

    Where do excessive variants come from?

    Responsive code may pass the current viewport width directly, producing values such as 731, 732, and 733. Editors may create a new preset for each campaign. Device-pixel-ratio logic can multiply widths again. Query parameters can be serialized in different orders. Attackers can deliberately request random combinations.

    Even legitimate features create a cross-product. Ten widths multiplied by four crops, three quality tiers, and three formats already allow 360 outputs for one source. Most applications use only a small fraction.

    The problem affects transformation CPU, storage, cache hit ratio, purge scope, and logs. It can also lengthen cold responses for real users if abusive work competes for processing capacity.

    How do width ladders and presets help?

    Map arbitrary requested widths to an approved responsive width ladder. The application can round up to the next candidate so visual quality is preserved. Enforce the same mapping on the server or signing layer, not only in a client helper.

    Use named presets for repeated crop and quality intent. A product-card-v1 preset is easier to audit than free-form width, height, gravity, sharpen, and quality fields. Keep lower-level operations available only to trusted administrative workflows that need them.

    Cloudinary documents named transformations as a reusable option in its transformation documentation. Provider features differ, but the governance principle is portable.

    Why is canonicalization required?

    Restrictions do not help if one allowed transform has many spellings. Normalize aliases, parameter order, numeric precision, default values, and source versions. Reject unknown fields. The cache key design guide explains the relationship between canonical input and stored identity.

    Do this before signing. A signature for raw, noncanonical strings can authorize duplicate representations. A central URL builder should emit exactly one string for one normalized request.

    If an edge cache and transformation service apply different normalization, inspect both. A provider may reuse one derivative internally while the CDN still stores many copies under raw URLs.

    Which limits should be enforced?

    Set maximum input pixels, output pixels, width, height, frame count, effect count, and processing time. Block upscaling beyond a deliberate threshold. Restrict remote origins and file types. Apply tighter rules to unauthenticated traffic.

    Use rate limits and quotas on derivative creation, not only total requests. A million requests for one warm thumbnail are cheaper than ten thousand unique expensive transforms. If the service exposes a cache-status or generated-variant signal, use it to distinguish them.

    For public URLs, consider signing any transformation outside a small allowlist. Expiry can control access, but a signature that permits arbitrary dimensions still allows a trusted caller or leaked token to create enormous variety. Sign policy-bounded inputs.

    OWASP’s guidance on denial of service provides the broader availability context. Image-specific limits translate that principle into measurable resource boundaries.

    What should you monitor?

    Track unique normalized transformations per source, new derivatives per minute, cold-transform latency, processing failures, transformation CPU if available, stored derivative bytes, and cache hit ratio. Segment by application, route, preset, and credential.

    Alert on rates and concentration. One source suddenly receiving thousands of widths is different from a planned catalog import. The top assets by variant count and the top transformations by creation rate are especially actionable views.

    Record rejection reasons. A spike in invalid widths may reveal a frontend bug rather than an attack. Sample raw requests safely so engineers can trace the caller without storing sensitive tokens.

    How do you clean up existing excess?

    First stop creation by enforcing the new policy. Deleting variants while callers still generate them only adds churn. Then identify derivatives that do not match approved normalized transformations and have not been requested within a retention window.

    Understand the provider’s deletion semantics. Removing a derivative may cause regeneration on the next request. Removing a source is materially different and can be irreversible. Test cleanup on a small asset cohort and retain a report of affected keys.

    Use the payload measurement workflow to confirm that a smaller set still serves appropriate resources. Variant reduction should not force every slot to download the largest image.

    On-demand transformation works best as a constrained API, not an infinite image calculator. A finite ladder, reviewed presets, canonical URLs, resource limits, and clear telemetry preserve the flexibility users need without accepting unbounded work.

  • Design image cache keys without surprises

    Design image cache keys without surprises

    Short answer: An image cache key should change when the source bytes or output pixels change, and remain stable when irrelevant request details change. Base it on a versioned source, canonical transformation, and representation variant, then test the actual key behavior at every cache layer.

    Image systems commonly have two related identities. The transformation service stores a derivative under an internal key, while the CDN stores an HTTP response under an edge key. If those rules disagree, the system can generate duplicates, serve the wrong format, or keep stale bytes after a source update.

    Which inputs must affect identity?

    Start with source identity and source version. An asset ID alone is insufficient if its bytes can be replaced. A version number or content hash makes each revision unambiguous and enables long-lived immutable caching.

    Every normalized operation that changes pixels must also affect identity: width, height, fit, crop, focal point, orientation, quality, format, background, and relevant effects. The URL anatomy guide shows how to canonicalize these fields.

    If output varies by a request header, that variation needs a correct cache strategy. Automatic format often depends on Accept. Private responses may depend on authorization but still represent the same underlying bytes. Decide whether access proof changes storage identity, delivery eligibility, or both.

    Which inputs should not affect identity?

    Tracking parameters, arbitrary query order, request IDs, and expired signatures usually should not create different pixel objects. Strip or normalize them before derivative identity is calculated. At the CDN, configure which query parameters matter rather than blindly including everything.

    Do not place secrets in a cache key or loggable URL. A signature is a proof, not a transformation. Some systems validate it and then normalize to a content key; others cache the signed URL as received. Understand the provider’s behavior before selecting expiry times and cache lifetimes.

    Cloudflare documents configurable dimensions in its cache key guidance. HTTP cache behavior, including freshness and validation, is defined in RFC 9111. Your image derivative rules sit on top of those semantics.

    How does canonicalization prevent fragmentation?

    Equivalent requests need one serialization. w=800&q=70 and q=70&w=800 should not create two entries. Neither should w=0800, a redundant default crop, or two aliases for the same fit behavior.

    Normalize in one typed URL builder. Sort fields, choose one spelling, round values, omit defaults, and reject unknown operations. If the provider normalizes internally but the CDN caches raw URLs, your application still needs canonical URLs to avoid edge duplicates.

    Presets should resolve deterministically. If a named preset changes meaning, version the preset. Silent changes can make one visible URL refer to old pixels at one edge and new pixels at another.

    What can go wrong with automatic format?

    If the same URL returns AVIF to one browser and JPEG to another, the cache must distinguish those representations. Standard Vary: Accept can express the relationship, but some CDNs use product-specific normalization to reduce the enormous variety of raw Accept headers.

    Verify with real requests. Send explicit capability headers, inspect Content-Type, Vary, age, and cache status, then repeat in both orders. A cache poisoning bug may only appear when the less-capable client follows the more-capable one.

    Format can also be explicit in the URL. This produces simple keys and observability at the expense of more markup or application logic. The format decision guide compares the approaches.

    How should invalidation work?

    Prefer versioned URLs over broad purges. When an original changes, emit a new source version. The old immutable derivative can expire naturally, while new requests cannot be confused with it.

    Purge remains useful for security incidents, legal removal, or a faulty transformation. Document whether a purge removes edge responses, derivative storage, or both. Test propagation time and partial failure rather than assuming one API call reaches every layer.

    Use reasonable negative caching for missing assets, but avoid turning a transient upload race into a long-lived 404. The upload workflow should publish delivery references only when assets are ready.

    How do you test a cache key policy?

    Create a matrix of requests that should match and requests that must differ. Reorder parameters, add ignored tracking data, vary a meaningful width, change source version, test format negotiation, and try expired versus valid signatures. Record response hash, content type, age, cache status, and timing.

    Sample production keys by normalized transformation. A sudden rise in unique variants per asset suggests a caller bypassed the width ladder or added an unbounded value. The guide to preventing variant explosion turns that signal into policy.

    Good cache identity is predictable enough to explain during an incident. If the team cannot state why two requests share or do not share bytes, the key design needs to be made explicit before traffic makes the ambiguity expensive.

Share with