Migrate to RunxBuild today!! Deploy More while Spending Less

Calculate your savings
unxBuild
Back to Blog Troubleshooting

Cloudflare Lazy Load: What It Actually Does, and Why Your Hero Image Should Skip It

Sean

Platform Writer

Sep 23, 2026
7 min read

Cloudflare does not have one feature called lazy load - what people mean by the phrase is usually one of three different things: the native HTML loading lazy attribute, which Cloudflare’s own documentation now recommends as the standard implementation; Mirage, Cloudflare’s image-optimization feature that defers and adapts image loading based on connection speed; and Rocket Loader, which defers JavaScript execution and has nothing to do with images at all despite frequently getting blamed for image-loading bugs. Knowing which one is actually running matters, because the wrong lazy-loading choice on exactly one image - the largest one visible without scrolling - actively hurts the metric Google uses to judge how fast a page feels.

Cloudflare Lazy Load: What It Actually Does, and Why Your Hero Image Should Skip It

This sorts out what each of Cloudflare’s related features actually does, when native lazy loading beats both of them, and why lazy-loading the wrong image is a self-inflicted performance regression rather than a performance win.

Table of contents

Native lazy loading: the HTML attribute

The loading lazy attribute on an img or iframe tag tells the browser to defer loading that element until it is close to entering the viewport, with zero JavaScript and no third-party service involved - it is a browser feature, not a Cloudflare one. Support is universal across current browsers, and it is what Cloudflare’s own learning center page on lazy loading now leads with as the recommended implementation.

It is also the cheapest possible fix, since it is one attribute added to markup that already exists: below-the-fold images, and offscreen iframes such as embedded video players, are the correct targets. It costs nothing to serve, needs no configuration in any dashboard, and works whether or not the site sits behind Cloudflare at all.

The browser’s own heuristic for ‘close to entering the viewport’ varies slightly between engines and is not something a page can configure directly, which is the trade-off for how little setup the attribute needs. For the vast majority of pages that variance is invisible; it only becomes worth knowing about when debugging a report that an image appeared later on one browser than another during testing.

<img src="/gallery/photo-12.jpg" alt="Product detail shot" width="800" height="600" loading="lazy">

Mirage: Cloudflare’s image feature

Mirage is a Cloudflare feature, available on paid plans, that defers and adapts image loading specifically, serving a lower-quality placeholder first on slower connections and swapping in the full image as bandwidth allows - it is closer to adaptive image loading than to the plain defer-until-visible behavior of the native attribute. It operates independently of the page’s own loading attributes, which is the direct cause of one of the more common support threads on Cloudflare’s community forum: images still appear to lazy-load or fade in even after the lazy attribute is removed from the markup, because Mirage is doing its own thing underneath.

Community reports also describe Mirage still affecting images after being toggled off in the dashboard, and conflicts between Mirage and Cloudflare’s separate Image Resizing feature. If a site sees lazy-loading-like behavior that does not match what is in its own HTML, checking whether Mirage is enabled - and disabling it if the native attribute is already doing the job - is the first thing to check before assuming the markup is wrong.

Rocket Loader: not an image feature at all

Rocket Loader defers the loading and execution of a page’s JavaScript until after the page’s content - text, images, fonts - has rendered, which speeds up perceived load time but has no direct relationship to image lazy loading specifically. It gets confused with image lazy loading constantly, mostly because both features are filed under Cloudflare’s Speed settings and both change when things visibly appear on the page, but Rocket Loader is a script-execution feature, not an image one.

The practical implication: if an image-loading bug shows up on a Cloudflare-proxied site, checking Rocket Loader is worth ruling out only if the images are being rendered by JavaScript in the first place, such as a lazy-loading library or a gallery component. If the images are plain img tags, Rocket Loader is very unlikely to be the cause and Mirage or the page’s own markup is the more likely place to look.

Why lazy-loading the hero image is a mistake

Largest Contentful Paint, one of Google’s core web vitals, measures how long it takes the largest visible element - almost always a hero image or a large above-the-fold photo - to render. Adding the lazy attribute to that specific image tells the browser to deliberately delay starting its download until it is confirmed to be near the viewport, which for the very first image on the page is immediately, but the deferral logic still adds a measurable delay before the browser even starts the request, directly working against the metric the attribute is supposed to help.

The fix is not removing lazy loading everywhere - it is scoping it correctly: the lazy attribute on everything below the fold, and either no loading attribute at all or an explicit eager value plus a high fetch priority hint on the one image that renders LCP. Getting this backwards is common enough that it shows up in real-world Core Web Vitals audits as a recurring, easily fixed regression.

<!-- hero image: load it immediately, at high priority -->
<img src="/hero.jpg" alt="Homepage hero" width="1600" height="900" loading="eager" fetchpriority="high">

<!-- everything else below the fold: defer it -->
<img src="/gallery/photo-1.jpg" alt="Gallery photo" width="800" height="600" loading="lazy">

Which one to actually use

For a typical site, the native lazy attribute applied correctly - deferred below the fold, eager above it - covers the whole problem without touching a Cloudflare dashboard setting at all, and it is the option Cloudflare’s own guidance now points to first. Mirage adds value specifically for visitors on slow or unreliable connections, where its adaptive quality behavior genuinely helps beyond what the native attribute does alone, but it is worth testing rather than assuming it stacks cleanly with markup that is already doing the deferral correctly.

Rocket Loader is a separate decision entirely, worth evaluating on its own JavaScript-execution merits and not as part of an image-loading fix. Turning on every Speed feature Cloudflare offers at once, without understanding what each one actually touches, is how a site ends up with three overlapping systems fighting over when an image should appear.

Checking what is actually happening on a live page

Before changing anything, confirm which system is in play: view the page source for lazy attributes already in the markup, check the Cloudflare dashboard’s Speed tab for whether Mirage and Rocket Loader are enabled, and use the browser’s network tab to watch when the hero image’s request actually fires relative to the page load. If the hero image’s request is visibly delayed and there is no lazy attribute in the markup, Mirage or an image-loading JavaScript library is the more likely cause, not the HTML.

This diagnostic order matters more than it sounds like it should, because guessing wrong means disabling the wrong feature, seeing no change, and concluding lazy loading is not the problem when it actually was - just implemented by a different layer than the one that got turned off.

A Lighthouse or PageSpeed Insights run after each change is worth more than reasoning about it in the abstract, since LCP timing is sensitive enough that a genuine fix should show up as a measurable number moving, not just a feeling that the page loads faster.

How this fits the rest of the stack

Getting this right is markup work more than infrastructure work, but the platform serving the page still matters for how fast that markup gets to a browser in the first place - a static site with a fast time to first byte gives the LCP image a head start before any lazy-loading decision even applies. The RunxBuild hosting calculator prices static hosting with the response headers and caching controls that pair with this kind of fix documented alongside it, not bundled into a black-box speed toggle.

Useful related references:

FAQ

Does Cloudflare have a lazy loading feature?

Not as a single dedicated feature. Cloudflare’s own guidance recommends the native HTML loading lazy attribute as the standard implementation. Separately, Cloudflare offers Mirage, which adapts image loading to connection speed, and Rocket Loader, which defers JavaScript execution - neither is the same thing as the browser’s native lazy loading.

What is the difference between Cloudflare Mirage and Rocket Loader?

Mirage is an image-specific feature that defers and adapts image quality based on the visitor’s connection speed. Rocket Loader defers JavaScript execution until after page content renders and has no direct relationship to images. They are frequently confused because both sit under Cloudflare’s Speed settings.

Why do my images still lazy load after I removed the loading attribute?

Mirage, if enabled on the Cloudflare account, applies its own image-loading behavior independently of the page’s own loading attributes, so removing the lazy attribute from the HTML does not stop it. Checking whether Mirage is enabled in the Cloudflare dashboard’s Speed settings is the next step.

Should I lazy load my hero image?

No. Lazy loading the largest visible image - usually the hero image - delays the browser starting its download and directly hurts Largest Contentful Paint, the metric that measures how fast that image appears. Use an eager or default loading value, plus a high fetch priority hint, on that one image, and reserve lazy loading for images below the fold.

How do I turn off Cloudflare’s automatic image lazy loading?

Check the Speed tab in the Cloudflare dashboard and disable Mirage if it is enabled; that is the feature responsible for Cloudflare-side adaptive image loading. Rocket Loader, a separate JavaScript-deferral feature, is configured in the same area but does not control image loading behavior.

#cloudflare lazy load#cloudflare mirage#rocket loader vs lazy loading#loading lazy html attribute#lcp image lazy loading