<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 3ev</title>
    <description>The latest articles on DEV Community by 3ev (@3ev).</description>
    <link>https://dev.to/3ev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3940844%2F613cb6a4-727c-45a7-9619-3933e693b120.png</url>
      <title>DEV Community: 3ev</title>
      <link>https://dev.to/3ev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/3ev"/>
    <language>en</language>
    <item>
      <title>Why Most Websites Still Fail at Image Delivery in 2026</title>
      <dc:creator>3ev</dc:creator>
      <pubDate>Thu, 21 May 2026 12:57:38 +0000</pubDate>
      <link>https://dev.to/3ev/why-most-websites-still-fail-at-image-delivery-in-2026-5a0n</link>
      <guid>https://dev.to/3ev/why-most-websites-still-fail-at-image-delivery-in-2026-5a0n</guid>
      <description>&lt;p&gt;Images are one of the biggest performance bottlenecks on the web, and one of the most consistently mishandled. Teams upload whatever they have, usually a large JPG or PNG, and the site deals with the consequences: slow LCP, inflated bandwidth, and Core Web Vitals scores that quietly drag down search rankings.&lt;/p&gt;

&lt;p&gt;This post covers what actually moves the needle: modern formats, lazy loading done right, and a just-in-time delivery pipeline we built to handle all of it automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real cost of unoptimised images
&lt;/h2&gt;

&lt;p&gt;Google's Core Web Vitals have made image performance impossible to ignore. Largest Contentful Paint (LCP), the time it takes for the biggest visible element on a page to render, almost always a hero image, is a direct ranking signal.&lt;/p&gt;

&lt;p&gt;An unoptimised hero image doesn't just annoy users. It hurts SEO.&lt;/p&gt;

&lt;p&gt;The fix isn't just "compress more". It's about delivering the right format, at the right size, to the right device, ideally without creating a manual process that breaks down as soon as a content editor touches it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image CDN vs traditional CDN
&lt;/h2&gt;

&lt;p&gt;A traditional CDN answers: "where is this visitor?"&lt;/p&gt;

&lt;p&gt;An image CDN answers: "what does this visitor actually need?"&lt;/p&gt;

&lt;p&gt;The difference is transformation. Instead of serving a static file from a nearby edge node, an image CDN generates the optimal variant on request: correct format, dimensions, and compression, then caches it for future visitors.&lt;/p&gt;

&lt;p&gt;Pre-generating every variant for every image at every breakpoint is impractical at scale. Dynamic, on-demand generation with caching solves this cleanly: one source file, infinite appropriate outputs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0ohpr0r73q0q6ds6kyz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0ohpr0r73q0q6ds6kyz.png" alt="Diagram comparing a traditional CDN delivering the same 1MB image to desktop, tablet and mobile devices versus an image CDN serving optimised image sizes for each device" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AVIF and WebP: use them, automate the negotiation
&lt;/h2&gt;

&lt;p&gt;Most sites are still serving JPEG and PNG. Both formats carry significant overhead compared to their modern replacements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WebP&lt;/strong&gt;: typically 25–35% smaller than JPEG at equivalent quality. Full browser support. Handles transparency and animation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AVIF&lt;/strong&gt;: even better compression than WebP, especially for photography. Browser support is now broad enough to treat it as the primary format in 2026, with WebP as fallback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Format negotiation happens via the &lt;code&gt;Accept&lt;/code&gt; request header - the browser declares what it supports, and your delivery layer responds accordingly:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Accept: image/avif,image/webp,*/*&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You shouldn't need to manage this manually. A properly configured image CDN handles it automatically. If you're still manually exporting WebP variants before uploading, your pipeline needs work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy loading: what to do and what not to do
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;loading="lazy"&lt;/code&gt; is now a browser native, zero-JavaScript way to defer offscreen images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there's one critical mistake we see constantly: lazy loading the LCP image.&lt;/p&gt;

&lt;p&gt;Your hero image is almost always your LCP element. Lazy loading it delays the browser from fetching it, which tanks your LCP score. &lt;/p&gt;

&lt;p&gt;Never lazy load above the fold. Always lazy load below the fold.&lt;/p&gt;

&lt;p&gt;For your hero specifically, go further with a preload hint in &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/hero.webp"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the browser to fetch it before it even starts rendering the page. A meaningful gain for LCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we built a just-in-time image pipeline
&lt;/h2&gt;

&lt;p&gt;We built a custom image CDN that transforms images at request time rather than upload time. The mental model is borrowed from JIT compilation: don't generate the thing until it's actually needed, then cache the result.&lt;/p&gt;

&lt;p&gt;The flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Editor uploads a standard image to the CMS (any CMS, this is fully agnostic)&lt;/li&gt;
&lt;li&gt;A visitor requests a page&lt;/li&gt;
&lt;li&gt;The CDN intercepts the image request&lt;/li&gt;
&lt;li&gt;If a cached variant exists for that device/format/size combination then serve it immediately (~43 ms average)&lt;/li&gt;
&lt;li&gt;If not, transform in real time, cache the result, serve it (~400 ms first hit)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjh0eq0up15vsot9hoaa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjh0eq0up15vsot9hoaa.png" alt="Flowchart showing an on-the-fly image optimisation pipeline where user requests pass through a CDN cache layer and images are transformed in real time into optimised formats before delivery" width="800" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The transformation step handles format conversion (AVIF/WebP with JPEG fallback), responsive resizing based on the requested dimensions, and compression tuned for visual fidelity.&lt;/p&gt;

&lt;p&gt;What this looks like operationally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Storage reduced by ~80% (only source images stored, not variant explosions)&lt;/li&gt;
&lt;li&gt;Bandwidth costs cut by up to ~90% once cache warms up&lt;/li&gt;
&lt;li&gt;Cache hit rates reaching 90%+ on established sites&lt;/li&gt;
&lt;li&gt;43 ms median delivery for cached images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 400 ms first-hit cost is the trade-off for not pre-generating everything. In practice it's still faster than most unoptimised pipelines, and it disappears as the cache builds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worth reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://web.dev/articles/lcp" rel="noopener noreferrer"&gt;Core Web Vitals&lt;/a&gt; — Google's overview&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/articles/lcp" rel="noopener noreferrer"&gt;Largest Contentful Paint (LCP)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/docs/performance/insights/image-delivery" rel="noopener noreferrer"&gt;Improving image delivery with next-gen formats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.3ev.com/insights/delivering-images-just-in-time/" rel="noopener noreferrer"&gt;How 3ev benefits from just-in-time image delivery techniques&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>webperf</category>
      <category>cdn</category>
    </item>
  </channel>
</rss>
