Skip to content

Technical Guides

Why Your Image CDN Is Not Improving LCP: 7 Configuration Mistakes

Installed an image CDN but Largest Contentful Paint is still bad? Here are the seven configuration mistakes that usually block LCP gains, with fixes for HTML, WordPress, and Next.js.

By · Editor

Last verified Jun 1, 2026

Your image CDN is probably working. Your LCP setup may not be.

That is the part most people miss.

An image CDN can resize, compress, convert, cache, and deliver the LCP image faster. But it cannot fully fix a hero image that the browser discovers late, lazy-loads by mistake, renders after JavaScript, or requests at the wrong size.

TL;DR: If an image CDN is not improving LCP, check the LCP subparts before blaming the provider. The common mistakes are lazy-loading the hero image, missing srcset and sizes, late CSS or JavaScript discovery, no fetchpriority, too many cold-cache variants, a new third-party CDN connection, and render delay from CSS or JavaScript. The CDN mainly fixes image bytes and delivery. Your markup fixes discovery and priority.

Tip

My Short Verdict

An image CDN is worth using for LCP when the LCP resource is too large, too far away, or served in the wrong format. If the request starts late or the image waits behind JavaScript, fix the page implementation first.

Chrome image delivery insight documentation


How to Diagnose the Real LCP Bottleneck

Do not start by changing CDN providers.

Start by opening PageSpeed Insights, Chrome DevTools Performance, or WebPageTest and identifying the actual LCP element. Then check the LCP breakdown.

Google's LCP optimization guide breaks the metric into four parts:

LCP partWhat it meansDoes an image CDN fix it?
TTFBTime until HTML starts arrivingNot directly
Resource load delayTime before the LCP image request startsOnly indirectly
Resource load durationTime spent downloading the imageYes, this is the main CDN win
Element render delayTime after image load before it rendersNo

This table explains most failed CDN projects.

If resource load duration is the big number, your image CDN setup probably needs better sizing, format, compression, cache, or edge delivery.

If resource load delay or render delay is the big number, the CDN is not the main problem.

For the broader testing setup, read my full image CDN LCP test guide. This page is the troubleshooting version.


What Usually Goes Wrong?

Here is the quick map.

SymptomLikely mistakeFirst fix
LCP image request starts lateImage hidden in CSS, JavaScript, slider, or client renderingPut the image in early HTML
CDN image is small but LCP still badRender delay or TTFB is dominantFix CSS, JS, server response, or hydration
PageSpeed says LCP image was lazy-loadedHero image has loading="lazy"Remove lazy loading from the LCP image
Mobile downloads a desktop-sized imageMissing or wrong srcset / sizesGenerate bounded responsive CDN URLs
First visit is slow, second visit is fineCold CDN transformPre-warm key variants and reduce URL variants
CDN URL is on a new domainConnection setup adds delayUse a custom CDN hostname or preconnect
LCP moves to another elementWrong element was being optimizedOptimize the real LCP element per viewport

That last one matters.

Desktop and mobile can have different LCP elements. A homepage can use a hero image on desktop and a text block on mobile. A product page can shift from gallery image to product title depending on layout.

Do not optimize the image you think is important. Optimize the image your tools show as LCP.


Mistake 1: You Lazy-Loaded the LCP Image

This is the easiest mistake to understand.

Lazy loading is for images the user may not see immediately. Your LCP image is the opposite. It is usually the biggest visible thing in the first viewport.

Bad:

<img
  src="https://cdn.example.com/hero.jpg?width=1200&format=auto"
  loading="lazy"
  width="1200"
  height="675"
  alt="Homepage hero"
>

Better:

<img
  src="https://cdn.example.com/hero.jpg?width=1200&format=auto"
  width="1200"
  height="675"
  fetchpriority="high"
  decoding="async"
  alt="Homepage hero"
>

The image CDN can make the file smaller. But loading="lazy" still tells the browser not to rush the image.

Use lazy loading below the fold. Keep the hero, product lead image, and article cover eager when they are likely to be the LCP element.

I covered the full setup in lazy loading images with an image CDN.


Mistake 2: Your CDN URL Is Optimized, but Your HTML Is Not Responsive

An image CDN URL is not magic if every device requests the same large variant.

This is common on WordPress themes, custom page builders, and quick migrations:

<img
  src="https://cdn.example.com/uploads/hero.jpg?width=2400&format=auto"
  width="2400"
  height="1350"
  alt="Hero image"
>

The file may be WebP. It may be compressed. It may be served from a CDN edge.

But mobile is still downloading a 2400 px image for a 390 px viewport.

Better:

<img
  src="https://cdn.example.com/uploads/hero.jpg?width=800&format=auto"
  srcset="
    https://cdn.example.com/uploads/hero.jpg?width=480&format=auto 480w,
    https://cdn.example.com/uploads/hero.jpg?width=800&format=auto 800w,
    https://cdn.example.com/uploads/hero.jpg?width=1200&format=auto 1200w
  "
  sizes="100vw"
  width="800"
  height="450"
  fetchpriority="high"
  alt="Hero image"
>

Chrome's image delivery insight looks for unnecessarily large downloads, modern formats, compression, and responsive sizing. An image CDN helps with those, but the browser still needs the right candidates.

Do not create endless widths either.

Use a small set of sensible breakpoints like 480, 800, 1200, and 1600. Too many unique widths can hurt cache efficiency.


Mistake 3: The Browser Discovers the Image Too Late

This is the configuration mistake that makes people unfairly blame the CDN.

The CDN cannot download an image before the browser knows the image exists.

Late discovery usually happens when the LCP image is:

  • a CSS background image
  • injected after JavaScript runs
  • inside a carousel
  • swapped after hydration
  • hidden behind a skeleton loader
  • loaded by a tag manager or personalization script
  • not present in the initial HTML

Risky:

<div class="hero-image"></div>
.hero-image {
  background-image: url("https://cdn.example.com/hero.jpg?width=1200");
}

Better:

<img
  src="https://cdn.example.com/hero.jpg?width=1200&format=auto"
  width="1200"
  height="675"
  fetchpriority="high"
  alt="Product dashboard"
>

CSS background images can be valid for decoration. They are not my first choice for the main LCP hero.

For LCP, boring HTML usually wins.


Mistake 4: You Did Not Give the LCP Image Priority

Browsers already prioritize resources, but they do not always know which image is the visual winner.

That is where fetchpriority="high" helps.

MDN documents fetchPriority as a browser hint for prioritizing an image fetch, with support across latest devices and browsers since October 2024. It is not a guarantee. It is a signal.

Use it on the one likely LCP image:

<img
  src="https://cdn.example.com/hero.jpg?width=1200&format=auto"
  width="1200"
  height="675"
  fetchpriority="high"
  alt="Hero image"
>

If the image is discovered late, preload can help:

<link
  rel="preload"
  as="image"
  href="https://cdn.example.com/hero.jpg?width=1200&format=auto"
  fetchpriority="high"
>

For responsive images, preload with imagesrcset and imagesizes so the browser can choose the right candidate.

Do not preload every above-the-fold image. That creates competition and can make LCP worse.

One LCP candidate gets priority. The rest should behave normally.


Mistake 5: Your CDN Cache Is Cold or Fragmented

First-request image transforms can be slower than repeat requests.

That is normal. The CDN may need to fetch the original, resize it, convert it, compress it, store the result, and then serve it.

The problem starts when your site keeps generating unique image URLs:

  • width=781
  • width=782
  • width=783
  • quality=79
  • quality=80
  • quality=81
  • random cache-busting query strings
  • personalized crop values
  • unbounded DPR variants

Now the CDN is always doing first-time work.

Fix it by limiting variants:

SettingBad patternBetter pattern
Widthsevery rendered pixel widthfixed breakpoints
Qualityper-template guessesone default per image type
Formatmanual format per pageformat=auto when supported
Cropsrandom dimensionsnamed aspect ratios
Cache keystracking params includedstrip non-image params

For important pages, pre-warm the exact hero variants after deployment.

This matters most for ecommerce, news, landing pages, and pages where the first uncached visitor may be a real buyer.


Mistake 6: You Added a New CDN Hostname Without Thinking About Connection Cost

A CDN can be faster after the connection is ready.

But a new hostname can add DNS, TCP, TLS, and HTTP negotiation before the first image byte arrives. On a warm connection this is less visible. On a cold mobile visit it can matter.

This is not a reason to avoid image CDNs. It is a reason to configure them cleanly.

Use one of these patterns:

  • serve images from the same site hostname through a reverse proxy
  • use a stable custom CDN hostname like img.example.com
  • add preconnect for the CDN origin when the LCP image is on that host
  • avoid splitting critical images across several CDN domains
  • make sure HTTP/2 or HTTP/3 is enabled
  • keep cache headers long for immutable transformed images

Example:

<link rel="preconnect" href="https://img.example.com" crossorigin>

Do this only for important third-party origins.

Preconnecting to five services just because they exist on the page is not performance work. It is noise.


Mistake 7: Your LCP Problem Is Render Delay, Not Image Delivery

This is the uncomfortable one.

Sometimes the image downloads quickly and still does not render quickly.

Google's LCP guide lists common render-delay causes: render-blocking stylesheets, synchronous scripts in the head, JavaScript that adds the LCP element later, A/B testing tools that hide content, and long main-thread tasks.

In that situation, a smaller CDN image may not move the final LCP number much.

You have to fix the render path:

  • reduce render-blocking CSS
  • inline only small critical CSS
  • remove heavy above-the-fold animations
  • avoid hiding the hero until JavaScript finishes
  • reduce hydration work
  • remove A/B testing flicker wrappers from the hero
  • keep the LCP image and text present in server-rendered HTML

This is why I like the LCP subpart breakdown.

It stops you from endlessly compressing an image when the image is already loaded and waiting for the page to render.


The LCP Image Fix Checklist

Use this checklist before changing providers.

1. Confirm the real LCP element

Check mobile and desktop separately. Do not assume the hero image is always LCP.

2. Check when the image request starts

If the request starts late, fix discovery, preload, and priority.

3. Check transfer size

If the image is still huge, fix responsive widths, format, compression, and quality.

4. Check rendered size vs intrinsic size

If a 390 px mobile slot downloads a 2400 px image, the CDN is configured badly.

5. Remove lazy loading from the LCP image

Use lazy loading below the fold, not on the hero.

6. Add explicit dimensions

Use width and height so the browser can reserve space and avoid layout instability. web.dev recommends image dimensions for lazy-loaded images and the same rule is useful for normal images too.

7. Add priority intentionally

Use fetchpriority="high" on the likely LCP image. Use preload only when discovery is genuinely late.

8. Check cache behavior

Look for cache-control, CDN cache hit status, and whether your URL variants are bounded.

9. Check render delay

If the image loads but LCP waits, fix CSS, JavaScript, long tasks, and hydration.

10. Re-test with field data

Lab tests are useful for debugging. CrUX or your own RUM data tells you what real users see after the change.


WordPress Checks

For WordPress, I would check these first:

  • featured image is not lazy-loaded when it is above the fold
  • theme outputs srcset and sizes
  • CDN plugin is not rewriting URLs twice
  • page cache and image plugin are not fighting each other
  • first hero image has width and height
  • slider, animation, or page builder is not hiding the LCP image
  • image derivatives are cached and not generated on every request

The common WordPress failure is plugin stacking.

One plugin lazy-loads. Another rewrites images. Another adds WebP. Another adds a CDN URL. The final HTML looks optimized until you inspect the real LCP image and see the browser gets mixed signals.

Pick one tool to own image optimization.

For provider selection, start with best image CDNs for WordPress.


Next.js Checks

For Next.js, check the component output, not only the React code.

The final HTML should include the right image URL, dimensions, srcset, and priority behavior.

For a likely LCP image:

<Image
  src="/hero.jpg"
  alt="Product dashboard"
  width={1200}
  height={675}
  fetchPriority="high"
/>

If the image is discovered too late, use the current Next.js image API intentionally. The Next.js Image docs say Next.js 16 deprecates priority in favor of clearer preload behavior, and loading="eager" or fetchPriority="high" is enough in most cases.

Do not use preload, loading="eager", and fetchPriority="high" everywhere.

One page can have only one real LCP winner per viewport. Treat it that way.

For loaders, static export, and CDN provider tradeoffs, use the Image CDN for Next.js guide.


Should You Switch Image CDN Providers?

Sometimes, yes.

But only after you know the provider is the bottleneck.

Switch providers when:

  • the CDN cannot generate the widths you need
  • format negotiation is weak or missing
  • transform latency is consistently high
  • cache hit ratio stays poor even with bounded URLs
  • the provider is far from your main audience
  • pricing forces you to avoid good responsive variants
  • debugging headers are missing

Do not switch providers when:

  • the LCP image is lazy-loaded
  • the image is injected after JavaScript
  • your HTML requests one giant variant
  • your TTFB is already too slow
  • CSS or JavaScript blocks rendering
  • the LCP element is text

If you are choosing from scratch, compare the best image CDNs and the paid image CDN options.

The cheapest useful test is often BunnyCDN Optimizer because the cost is predictable. Use coupon THEWPX for $5 free credit through this BunnyCDN signup link if you want to test it on a real page.


FAQ

Frequently Asked Questions

Why is my LCP still slow after adding an image CDN?

Because the CDN may only be fixing resource load duration. If your LCP image is discovered late, lazy-loaded, blocked by JavaScript, or waiting behind render-blocking CSS, the final LCP number can stay bad even when the image file is smaller.

Can an image CDN make LCP worse?

Yes, if it adds a new connection cost, generates cold variants on every request, serves the wrong image size, or breaks the original responsive image markup. The fix is usually configuration, not abandoning CDNs.

Should I preload my CDN hero image?

Preload only the likely LCP image when discovery is late. If the image is already present early in the HTML, fetchpriority="high" is often enough. Do not preload several competing hero images.

Is WebP or AVIF enough to fix LCP?

No. WebP and AVIF reduce bytes, but LCP also depends on discovery, priority, TTFB, cache behavior, dimensions, and render delay. A smaller image can still be late if the browser starts the request late.

What is the fastest way to debug image CDN LCP?

Find the LCP element, then check request start time, transfer size, rendered size, file format, cache status, priority, lazy-loading, and render delay. That tells you whether to fix CDN settings, HTML markup, or frontend rendering.

Does `fetchpriority=high` replace an image CDN?

No. fetchpriority="high" tells the browser which image to fetch sooner. An image CDN makes the fetched image smaller, correctly sized, cached, and closer to the user. They solve different parts of the LCP problem.

Summing Up!

If your image CDN is not improving LCP, do not panic and do not switch providers immediately.

First, inspect the LCP breakdown. If the image download itself is slow, fix CDN format, compression, width, quality, cache, and edge delivery. If the request starts late or rendering waits after the image loads, fix your HTML, priority hints, CSS, JavaScript, and framework setup.

My practical rule is simple: CDN fixes bytes. HTML fixes discovery. Frontend performance fixes render delay. You need all three before LCP becomes consistently good.

Free$5Credit
Live Offer

BunnyCDN · $0.01/GB

CodeTHEWPX
Claim