Using CDN often makes LCP worse due to resource distribution strategies or configuration issues. Many websites, after connecting to CDN, still load LCP elements (such as above-the-fold large images, Hero Banners) from the origin server, or fail to enable HTTP/2, Brotli compression, and cache prewarming, causing requests to increase by 100–400ms. In real cases, unoptimized CDN can cause LCP to rise from 2.1s to over 3.0s.
Solutions include: caching LCP images to CDN edge nodes, enabling preload, optimizing DNS resolution (reducing approximately 50–120ms), and avoiding cross-region node back-to-origin, thereby keeping LCP stably within Google’s recommended 2.5s.

Cache LCP Images to CDN Edge Nodes
When users open a page, LCP is often the above-the-fold hero image.If this image is already cached in the CDN node closest to the user, the request typically takes only a short path; if it misses, it has to go back to the origin once more, adding 1 round trip to the origin server and origin processing time. For cross-continental access, this step commonly takes 200–800 milliseconds; in 4G networks or cold cache scenarios, LCP can easily drag from 2.3 seconds to over 3 seconds. Google still uses within 2.5 seconds as the good LCP target.
Three Types of Configuration Issues
Putting LCP images on a CDN domain doesn’t guarantee that edge nodes will keep them. Cloudflare’s default behavior is to first check the cache headers returned from the origin; without separately setting Edge Cache TTL, whether edge caching keeps content and for how long are both affected by Cache-Control and Expires. The result users see is straightforward: the same above-the-fold image might be a local hit in the morning, but by afternoon it may have expired and requires another origin request. The good threshold for LCP is still within 2.5 seconds, measured against whether 75% of page visits meet this target; an extra 300–700 milliseconds can drop the page from good to needs improvement.
Let’s first look at cache headers and edge TTL. If the origin returns max-age=60 for an image, edge nodes will likely treat it as a short cache object of around 60 seconds; above-the-fold images may expire and refresh every minute. For low-traffic pages, early visitors often get cold cache responses. This is most common with campaign pages, feature pages, and registration pages: in the first 10–30 minutes after launch, traffic isn’t dense enough for many PoP nodes to warm up their cache, and visitors from Europe, North America, and Australia will progressively trigger their first origin requests. Cloudflare also provides separate Edge Cache TTL rules, and their documentation examples show configurations that cache resources at the edge for 1 day; without this step, the edge layer typically just “follows the origin’s lead.”
At this point, the problem has shifted from “whether there’s a CDN” to “how long is the CDN caching and how stable is it across nodes.” The next common layer is URLs themselves fragmenting the cache. Business side thinks it’s the same Hero image, but CDN side might see 4, 8, or 16 different objects:
-
/hero.avif?w=1280 -
/hero.avif?w=1280&ref=email -
/hero.avif?w=1280&ref=ad-7 -
/hero.avif?w=1280&session=8f3...
As long as query parameters enter the cache key, edge nodes will build separate cache entries for each version. When users arrive from email, ads, or organic search, they see the same above-the-fold area, but it may correspond to different URLs behind the scenes, fragmenting the hit rate. Cloudflare’s cache configuration documentation specifically provides custom cache key and cache rules to address these “same resource, different keys” situations.
After URLs get fragmented, users experience very concrete differences that are easy to misdiagnose as “random network slowness.” The following three symptoms are common:
-
Same landing page: desktop LCP 2.2 seconds, mobile ad traffic becomes 3.0 seconds
-
Homepage is stable, but入口 with campaign parameters is slow by 400–900 milliseconds
-
A/B test only changes copy, image file hasn’t changed, but above-the-fold image triggers origin request again
-
Returning users are fast, new visitors are slow, difference typically 0.3–1.0 seconds
These differences don’t average out because Chrome statistics are based on actual访问 data, and LCP thresholds look at 75th percentile; as long as a batch of traffic sources consistently hits poor conditions, reports will remain elevated long-term.
Going deeper, the third type of problem isn’t “cache miss” but “discovered too late.” Even if an image is already on edge nodes, the browser may discover it too late to make it in time for above-the-fold rendering. Chrome’s LCP breakdown explicitly includes resource discovery and resource loading phases; if the LCP image is in CSS background, the browser typically needs to fetch CSS, parse CSS, then discover it needs to request the image. If the image is inserted into DOM after script execution, the request timing pushes back even further. So users see: HTML has arrived, text is there, but the above-the-fold hero image is still blank for 200–600 milliseconds.
At this stage, the most problematic patterns typically fall into these categories:
-
Above-the-fold image implemented as CSS
background-image -
Carousel component loads script first, hero image inserted by JS
-
Responsive images exist, but first actually-displayed resource isn’t preloaded
-
<img>lacksfetchpriority="high", browser processes with default priority -
Simultaneously preloading 5–10 resources, resulting in none being early enough
MDN’s explanation offetchpriorityis clear: it’s just a priority hint, not a guarantee of absolute order, but it can help browsers process that image earlier. web.dev has also noted that preloading can improve LCP image timing, but preloading too many resources dilutes the priority effect.
Looking at these three types of problems in a single chain makes it easier to understand why users feel “there’s already a CDN, but the page is still slow.” A real visitor experience often unfolds like this: browser first gets HTML, takes 100–300 milliseconds to parse the above-the-fold structure; if the hero image is hidden behind CSS or JS, add another 1 CSS request or 1 JS initialization; browser finally discovers the image URL, but the URL has extra parameters, missing the existing edge cache; CDN node makes an origin request, plus origin processing time, adds 200–800 milliseconds; finally image download and decoding starts. Each step alone isn’t extreme, but combined, LCP easily adds 0.6–1.4 seconds.
From an implementation perspective, the troubleshooting sequence can be written more specifically in the main text, so readers can immediately compare against their own sites:
-
Check response headers: above-the-fold image
Cache-Controlis 60 seconds, 5 minutes, or 1 day or more -
Check edge policy: was Edge Cache TTL separately set for Hero images
-
Check cache keys: do marketing parameters, session parameters enter the key
-
Check discovery timing: is the hero image a native HTML
<img>, or late-inserted by script -
Check priority: was
fetchpriority="high"added to the hero image -
Check preloading: are you only preloading 1 above-the-fold image, not a whole image library
All these checkpoints correspond to behavior descriptions in public documentation, not guesswork.
First visit from London, hero image URL has ad parameters, edge MISS, origin back to US East Coast, LCP reaches 3.1 seconds; second visit from same region, parameters cleaned, edge HIT, browser immediately discovers <img> in HTML, LCP returns to 2.2 seconds. Both visits have nearly identical content, the difference is cache headers, cache keys, and discovery timing.
Usually when seeing this comparison, it’s immediately clear: the problem isn’t “image format not switched to WebP/AVIF,” but how many steps were added to the request path. Google’s public recommendation remains keeping LCP under 2.5 seconds, and web.dev mentions that 40% of sites still don’t meet the recommended threshold—LCP is inherently the hardest CWV metric to handle.
Going one layer further, file size makes the first three types of problems more pronounced. Even if an image hits edge cache, if the actual above-the-fold delivery is 700 KB or 1.2 MB, downloading and decoding on mobile networks will still extend LCP; but the same sized file shows a bigger difference between HIT and MISS scenarios because MISS first adds origin request latency, then starts file transfer. web.dev’s responsive images documentation repeatedly emphasizes that browsers should receive images “suited to the current device,” not always serving desktop-sized images; otherwise, downloading 1600 px images on a 390 px wide phone inherently adds above-the-fold burden.
At this point in the content, a complete logic path emerges: edge TTL too short, nodes can’t retain images; URL too fragmented, same image split into multiple copies; browser discovers it late, so even a cache hit doesn’t help. As long as any two of these combine, LCP exceeding 500 milliseconds is common; when all three exist, a page dropping from 2.3 seconds to 3.3 seconds is not an exaggeration.
Hero image is slow to appear
Users can’t tell whether it’s an “edge miss” or “an extra trip to origin”. Users only see the hero image being late by 300ms, 600ms, 1 second. The good target for LCP is still under 2.5 seconds, and it looks at the 75th percentile page visits; if a batch of users are consistently slow, the report will be high for a long time. Google’s public statement has always evaluated based on this metric.
First-time visits most easily amplify the problem. When the CDN node doesn’t have that hero image locally, after the request reaches the node, it has to fetch the file from the origin again. If the origin is in Virginia and the user is in Frankfurt or Sydney, what’s added isn’t just a local read, but a cross-region network round trip, plus origin server processing time. Cloudflare’s documentation makes it clear: by default, it follows the origin’s cache headers; without appropriate cache conditions or separate Edge TTL, resources may continue to go back to origin.
Slow first visits aren’t just about “images coming late”. More commonly: HTML arrives first, the title displays first, the hero image position stays empty for 0.4–1.2 seconds, and users may mistakenly think the page hasn’t finished loading. Chrome’s LCP breakdown divides this into stages like resource discovery, resource request, resource completion, and element rendering; whichever stage is late, LCP follows.
-
When new visitors access ad pages, the node doesn’t have the hero image cached yet, adding 1 origin round trip to the request chain
-
In the first 10–30 minutes after traffic starts flowing, many PoPs are still in cold cache state
-
The same page might be 2.3 seconds in a local office network, but easily reaches 3+ seconds with cross-continental access
-
Faster second refresh doesn’t mean the first-time problem doesn’t exist; CrUX and real user stats will still record the first visit
-
If the hero image file is 500 KB, 900 KB, MISS scenarios will also add download time on top
-
When edge node hit rate is unstable, the same URL can be fast in the morning and slow in the afternoon, because it goes back to origin after expiry
At this point, the chain problem is clear: first visits are slower, not because of the word “first” itself, but because the cache hasn’t been prepared yet in the node closest to the user. Go one step further: the farther from the origin, the more easily the difference shows. The browser connects to the nearest CDN node first, which looks like “global distribution”; but as long as that image isn’t local to the node, the node still has to fetch the file from the origin. The user only initiated 1 request, but what actually happened behind the scenes was 2 network transfers.
When accessing across regions, those extra hundreds of milliseconds don’t disappear evenly. LCP only cares about when the largest content on the page finishes rendering. For product detail pages, news homepages, and SaaS landing pages, this element is usually the hero image. If that image is late by 400 milliseconds, LCP will roughly be late by close to 400 milliseconds. In Google’s documentation on optimizing LCP, the focus is also on two requests: the initial HTML and the LCP resource itself.
-
Users in London accessing a US East Coast origin server will have an extra transoceanic round trip on cache miss compared to local hit
-
Users in Melbourne opening a European site, when the node doesn’t have the image, the extra wait is often more noticeable than same-continent access
-
Within the same batch of pages, North American user LCP is 2.4 seconds, European users 2.9 seconds, common cause is different edge coverage and origin location
-
When the site concentrates the origin server in 1 region, the farther visitors are, the more likely to bear the back-to-origin cost
-
If the hero image is updated without prewarming, the first batches of visitors in new regions usually experience a cold start
-
Even if other static files on the page are all hits, it can’t offset the hero image MISS because LCP only counts the completion time of the largest element
After crossing regions, mobile networks amplify the wait further. In 4G or poor Wi-Fi environments, network jitter, queuing, and packet loss retransmission are more noticeable than wired networks; if the LCP image still has to make an extra back-to-origin trip, users are more likely to feel “images are slow by half a beat”. Both Google and Chrome documentation place heavy emphasis on the start timing of resource requests, because initiating a request late isn’t just 50ms more on mobile networks, but hundreds of milliseconds more.
There’s another point often overlooked: just because an image is cached at the edge node doesn’t mean the user will necessarily feel fast. The browser must discover the image URL before it can send a request. If the hero image is in CSS background-image, the browser typically needs to download and parse the CSS first; if the hero image is inserted by a carousel script, it still needs to wait for JS initialization. In other words, the slowness users perceive is sometimes half from CDN miss, and half from late browser discovery.
-
If the hero image is in HTML
<img>, the browser can discover the request target earlier -
If the hero image is in CSS background, it often waits for 1 extra CSS request and parsing process
-
If the hero image is inserted into DOM by JS, the request start timing continues to shift back by hundreds of milliseconds
-
Adding
fetchpriority="high"to the LCP image makes the browser allocate request priority earlier -
If the hero image is mistakenly set to
loading="lazy", Chrome documentation explicitly advises against this -
Preload should point to the image that will actually display on the initial screen; preloading 5–10 images dilutes the priority effect
Assuming HTML arrives in 200ms, browser parsing takes 100ms; the hero image is hidden in CSS background, adding another 1 style request wait; the browser finally discovers the image URL, but the edge node has no cache, so back-to-origin adds an extra 300–800ms; if the image file itself is 700 KBdownloading and decoding on 4G will continue to drag it further. Users don’t care which step caused the problem; they only see the hero image taking forever to show up.
Looking at real reporting, why certain traffic sources appear worse. Google evaluates LCP at the 75th percentile, not the average. In other words, as long as there’s a sufficient number of people among ad traffic, new visitors, long-distance visitors, and mobile network visitors who are consistently slow by 0.5–1.0 seconds, the entire page may fall out of the good range. Categorizing a local problem as “occasional” isn’t practically helpful because reports aren’t calculated by subjective feeling, but by user visit distribution.
-
Ad traffic often carries query parameters, which can create multiple cached versions of the hero image URL
-
Landing pages with high new visitor ratios are more likely to persistently experience cold cache visits
-
When running ads in Europe and North America simultaneously, the side farther from the origin is often 0.3–0.8 seconds slower than the other side
-
Pages with mobile traffic exceeding 50% are more susceptible to request timing impacts on LCP
-
The first 1–2 hours after weekend promotions or new product launches, caches haven’t warmed up in all regions yet, and experience differences will be more pronounced
-
The same page meeting targets on desktop but failing on mobile is not uncommon; Google also recommends observing 75th percentile data separately for mobile and desktop
“Feeling noticeably slower” can be understood as a group of predictable people and scenarios: first-time visit, farther from origin, weaker network, later request discovery. Each factor adds hundreds of milliseconds, and combining two can take it from 2.4 seconds to 3.2 seconds. Users only see the hero image arriving late; the report records LCP getting worse; both sides are seeing the same thing, just using different language.
Enable preload
Many sites move images, fonts, and CSS to CDN, reducing request latency from 400–800ms to 80–200ms, but LCP still adds an extra 300–900ms. The common reason is that the browser discovers above-the-fold resources too late: HTML arrives first, CSS is parsed later, and fonts and above-the-fold images then trigger requests. The role of preload is not to make resources “download faster”, but to make them enter the request queue one discovery stage earlier. For above-the-fold large images, fonts, and CSS, this step is often more effective than simply switching to a faster CDN node.
What Resources Should Be Preloaded
First look at what the user will actually see within the first 2.5 seconds after the page opens, then decide what to preload. LCP measures the largest visible element, not the largest file size, nor the most requests. Many pages’ above-the-fold area has a total of 20 to 60 requests, but typically only 1 to 3 are truly suitable for preloading. Any more, and the browser’s early bandwidth gets divided; any fewer, and LCP resources may not start requesting until after CSS, fonts, or scripts are parsed.
The most common candidate resources usually fall into these 3 categories: above-the-fold hero images, above-the-fold fonts, and above-the-fold critical CSS. They share one common trait—they are visible before the user scrolls, and browsers may not naturally discover them early. For example, the hero image may be hidden in CSS, font files may be behind @font-face, or async CSS may be split into a second stylesheet. The files might only be 30KB, 90KB, or 180KB, but as long as the request starts 200 to 600ms late, LCP will move along with it.
Let’s start with images. For many SaaS homepages, media homepages, travel sites, and retail homepages, the most common LCP element is the above-the-fold image. It may be an <img> or a background-image. When the browser encounters a regular <img>, it can usually discover it earlier during HTML parsing; CSS background images require the CSS file to download and parse before the address is known. A typical chain looks like this: HTML arrives at 120ms, CSS starts at 260ms, parses at 430ms, and the background image doesn’t send its request until 450ms. Even if the image only takes 180ms to download, the LCP has already been dragged longer by the preceding wait.
Situations suitable for prioritizing image preloading can be evaluated as follows:
- Below-the-fold image occupies 25% or more of the visible area
- Image width typically ranges from 1200px to 2000px
- Resource size is between 80KB to 250KB
- Image is visible before user scrolls
- In DevTools, the image request start time is 300ms or more later than HTML
- Image is not a decorative icon, not a logo, not the second carousel image
If the above-the-fold area simultaneously contains a large image and a large heading, first determine which one is the LCP. Chrome Performance or Lighthouse usually indicates the LCP element. If it’s the hero image, preloading the image typically has higher priority than preloading the font. Because a 160KB hero image that starts 400ms late can alone push LCP from 2.2s to 2.7s; while a 32KB font file more often affects text rendering timing and layout stability, with a smaller impact, though it may still be noticeable on text-first pages.
Images also need to be categorized into several situations. Different implementations have different applicability.
| Page Situation | Whether Commonly Suitable for Preload | Reason |
|---|---|---|
Above-the-fold <img> positioned early in HTML |
Case by case | Browser can naturally discover it early |
| CSS background hero image | Yes | Natural discovery is delayed |
| Hero image inserted after JS rendering | Yes, but render path needs review | Both resource and element may appear late |
| Carousel first image that is initially visible | Case by case | Must confirm it is indeed the LCP |
| Carousel second image and beyond | No | Not visible to users initially |
| Thumbnails, card images | No | Above-the-fold area typically not large enough |
Next, let’s look at fonts. For many English sites, the largest above-the-fold element is not an image, but large headings, price text, or article titles. For example, news article pages commonly have H1 at 40px to 64px; SaaS homepages often have two-line main headings, each line nearly 60% to 80% of the visible area’s width; product page price areas occupy the top half of the screen on mobile. In these cases, font file request timing can easily affect LCP. Fonts usually wait until CSS downloads, parses, and constructs styles before the browser knows whether to fetch the woff2. If the font request starts at 500ms, and text is the main above-the-fold content, LCP will be delayed accordingly.
Pages suitable for font preloading commonly have these characteristics:
- LCP element is text, not an image
- Above-the-fold large headings use custom Web Fonts
- Font file is
woff2, size between 20KB to 60KB - Font only corresponds to 1 to 2 above-the-fold font weights
- Font request is 200 to 500ms later than HTML
- Fallback font and target font have significantly different character widths, easily triggering layout shifts
Note here: “only preload font weights that will actually be used above the fold.” Many pages load 300/400/500/700 four font weights with a total size of 120KB to 240KB, but above the fold only uses a 700 heading and 400 body text. Pulling down all four font weights early increases requests by 2 to 4 in the first 1 second, with returns usually not as good as only preloading 700. If the above-the-fold body text can first use system fonts, with other font weights slowly loaded below the body section, users will barely notice.
Whether a font is suitable for preloading can be judged in this order:
- Is the largest above-the-fold element text?
- Does this text depend on a custom font?
- Is this font used immediately above the fold?
- Can preloading 1 to 2 files cover above-the-fold text?
- Is it cross-origin, and does it need
crossorigin?
Once cross-origin fonts are candidates, the HTML typically needs to be written like this:
<link rel="preload" as="font" href="https://static.example.com/fonts/inter-700.woff2" type="font/woff2" crossorigin>
Without crossorigin, preloading and actual use may not fully reuse the cached resource. Although a single font is only about 30KB, on text-first pages above the fold, being 150ms to 300ms late is enough to push LCP from “Good” to “Needs Improvement.”
Beyond images and fonts, the third category is above-the-fold critical CSS. Not all CSS is suitable for preloading. A complete site’s CSS may be 80KB to 300KB, often split into base.css, layout.css, components.css, home.css, theme.css. Browsers naturally treat <link rel="stylesheet"> as very important, so “regular main stylesheets” may not need to be preloaded again. What is truly worth considering is: that stylesheet appears relatively late in the existing loading chain, and it controls above-the-fold layout, above-the-fold image dimensions, above-the-fold text styles, or above-the-fold visibility.
The following CSS types are closer to preload candidates:
- Above-the-fold specific
above-the-fold.css - Above-the-fold layout styles for homepage templates
- Styles controlling hero image container height, proportions, and display state
- Styles controlling above-the-fold heading font mapping
- Stylesheets that are async-split, where above-the-fold still depends on them
If a CSS file does not participate in layout and rendering during above-the-fold rendering, such as only managing footer, secondary tabs, user comments, or recommendation sections, then even if it’s only 18KB, it is not worth competing for early request slots. Because the browser can process only a limited number of high-priority resources in the first 700ms to 1200ms; adding one more causes other resources to queue longer.
The CSS judgment can be compressed into this table:
| CSS Type | Whether Commonly Suitable for Preload | Explanation |
|---|---|---|
Main stylesheet, already in <head> |
Rarely | Browser already handles it with high priority |
| Above-the-fold split CSS, loaded later | Yes | Suitable for early discovery |
| Page interaction styles | No | Not needed before above-the-fold rendering |
| Footer, comments, recommendation section styles | No | Not visible to users initially |
| CSS controlling above-the-fold image dimensions and visibility | Yes | Affects LCP element rendering |
Next, avoid a common misconception: treating “larger file” as “more deserving of preload.” This is not true. A 300KB video player script, though large, is not necessarily needed within the first 2 seconds of user entry; a 140KB hero image, though not large, is the LCP element, making it more suitable for early retrieval. Judging preload eligibility is not based on size ranking, but on “whether users will immediately need this in the first screen.” File size is only a secondary condition, because even if overly large resources are requested early, they may fill up early bandwidth.
A more practical set of filtering criteria can be used to narrow candidates from dozens down to 3 or fewer:
- Is it visible before user scrolls?
- Does it participate in LCP element rendering?
- Is browser natural discovery delayed?
- Can the resource size be controlled within 250KB?
- Can the resource count be controlled within 1 to 3?
- Will preloading trigger duplicate downloads?
If a resource simultaneously satisfies the first 3 items, it basically enters candidate status; if the first 3 items are satisfied but the size reaches 500KB or more, it needs to be considered together with format compression, resolution, and device strategies; if a page has already preloaded 4 to 6 resources, it should start removing rather than adding more.
There is also a page type difference that cannot be ignored. Homepages, article pages, product pages, and login pages often have different preload targets. On news article pages, LCP is commonly a headline or cover image; on product detail pages, it is often the main product image, with sizes typically 1200px to 1800px; on login pages, it may be a left promotional image or brand heading; on documentation pages, there is often no large image, and LCP may be the first section heading text. Applying the same preload rules to all templates will typically reduce hit rate. Differentiated configuration by page type makes it easier to keep preloading count at 1 to 2 while maintaining a high hit rate.
Templates can be roughly categorized as follows:
- Homepage: Hero image, above-the-fold heading font, above-the-fold layout CSS
- Article page: Cover image or heading font
- Product page: Main product image, price area font
- Login page: Brand image or promotional image
- Documentation page: Heading font, minimal above-the-fold styles
It is easier to operate if you understand preloading as “issuing an early entry pass to a few above-the-fold resources.” There are not many things that truly need to be used immediately above the fold on a page. For many sites that stabilize in the end, there are only 1 image + 1 font, or 1 image + 1 above-the-fold CSS. Control the quantity, choose the right resources, and users will see a complete above-the-fold area earlier, rather than downloading a bunch of files they cannot see yet.
How to Write, How to Test
Write it correctly first, then test. Many page issues aren’t about missing preload, but about tag placement, resource type, cross-origin parameters, or the actual matched filename not aligning. Within the first 100 to 300ms of parsing <head>, the browser decides the prioritization order for the initial batch of high-priority requests. If preload appears too late or gets injected by a script later on, the effect degrades noticeably. Placing the tag in the first half of <head> in the original HTML is usually more effective than inserting it via client-side JS after 500ms.
Let’s start with the writing. Attributes for images, fonts, and stylesheets can’t be mixed arbitrarily. Missing even one field can affect reuse and prioritization. A typical page only needs 1 to 3 preload tags. Once you exceed 4, you should start checking if they’re crowding out above-the-fold bandwidth. This pattern is more stable and suitable for above-the-fold hero images, fonts, and essential CSS:
<link rel="preload" as="image" href="/images/hero-1280.webp">
<link rel="preload" as="font" href="https://static.example.com/fonts/inter-700.woff2" type="font/woff2" crossorigin>
<link rel="preload" as="style" href="/css/above-the-fold.css">
<link rel="stylesheet" href="/css/above-the-fold.css">
For images, as="image" cannot be omitted. The browser uses as to determine request priority, content type, and cache reuse strategy. For fonts, besides as="font", you also need type="font/woff2" and crossorigin. Many sites host fonts on a separate static domain. Without crossorigin, you’ll see in DevTools that the preload request and the actual usage request don’t fully merge, causing the above-the-fold heading to wait an additional 100 to 250ms. For stylesheets, remember one thing: preload only handles early downloading; the element that actually applies the styles is still <link rel="stylesheet">.
If your site uses responsive images, the approach needs to go one step further. Desktop and mobile often use different images—desktop images might be 240KB while mobile images are only 95KB. If you hardcode the desktop image in the template for preload, on mobile you’ll typically waste 100 to 200KB downloading the wrong image. A more appropriate approach is to align preloading with actual device conditions, ensuring at least that <picture>, srcset, breakpoint logic, and above-the-fold requests are consistent. If you see the above-the-fold image being requested twice in DevTools Network panel—once as hero-desktop.webp and once as hero-mobile.webp—this is the problem to fix first, before any other optimizations.
This table serves as a reference for HTML:
| Resource | Required Attributes | Common Omissions | Result |
|---|---|---|---|
| Image | rel="preload" as="image" href |
Missing as |
Priority and reuse may be suboptimal |
| Font | as="font" type="font/woff2" crossorigin |
Missing crossorigin |
Preload and actual usage may not reuse |
| CSS | as="style" + stylesheet |
Only write preload, not stylesheet | File downloaded but styles don’t apply |
| Cross-origin image | as="image", with preconnect if needed |
Missing connection warmup | DNS/TCP/TLS still adds 80 to 300ms |
After writing, don’t stare at Lighthouse scores first. Instead, look at 3 more specific metrics first: when the LCP resource started requesting, when the LCP element actually rendered, and how many extra requests and volume were added during the above-the-fold phase. Lighthouse shows comprehensive results and is best saved for last. For investigation, Chrome DevTools, WebPageTest, and real user monitoring timelines are more useful. A common target is: get the above-the-fold LCP image or LCP font request start time to be 150 to 500ms earlier than before. If you only moved it up 30ms, the feel and scores are usually not noticeable.
Test in this order:
- Open Network and Performance in DevTools
- Clear cache, check Disable cache
- Simulate Slow 4G or regular 4G, CPU throttled to 4x
- Refresh the page, record HTML, CSS, and LCP resource start times
- Enable
preload, repeat the same conditions and test 3 times
When comparing, don’t just look at single results. Under mobile network conditions, single-instance fluctuations of 100 to 300ms are very common, especially for TLS handshakes and first packet arrival. Test 3 to 5 consecutive times and take the median for results closer to reality. For example, if the original version’s above-the-fold image starts requesting at 780ms / 810ms / 730ms, and after enabling preload it becomes 410ms / 450ms / 430ms, you can determine the request has indeed moved up by about 320 to 370ms. Then check if LCP has dropped from 2.9s to around 2.4s consistently—this makes the conclusion clearer.
Many people ignore warnings in the browser console, but there are often clues there. Chrome commonly warns “resource was preloaded but not used within a few seconds from the window’s load event”. When this appears, it’s usually not the browser “misunderstanding you”, but rather that the page preloaded a file that isn’t used in the above-the-fold content, or the filename, resource type, or device conditions don’t match. If a page preloads 3 carousel images but the above-the-fold only uses the first one, the latter two will often trigger a similar warning. Keeping them will just add 2 extra requests in the first 1 second of the above-the-fold phase.
When investigating, check these items first:
- Whether Console shows unused preload warnings
- Whether there are duplicate requests for similar resources in Network
- Whether above-the-fold image request priority has risen to High
- Whether LCP resource Start Time has moved up noticeably
- Whether HTML size has increased by 5KB to 20KB due to excessive inline configuration
If using a cross-origin CDN, also check connection preparation time. When a site puts HTML on the main domain, images on img.examplecdn.com, and fonts on fonts.examplecdn.com, the browser may need to establish 2 to 3 extra connections beforehand. On desktop, a new connection typically takes 80 to 180ms; on mobile, 150 to 400ms.
At this point, preload alone isn’t enough—you usually need to evaluate preconnect together. Otherwise, the browser learns the above-the-fold image address earlier but still has to go through DNS, TCP, and TLS first. In the timeline, it looks like “the request started earlier but is stuck at Initial connection”.
<link rel="preconnect" href="https://img.examplecdn.com" crossorigin>
<link rel="preload" as="image" href="https://img.examplecdn.com/hero.webp">
These two lines often appear together, especially when the above-the-fold image comes from a separate image CDN. When testing, don’t just look at total time—break it down into Queueing, Stalled, DNS, Initial connection, Request sent, Waiting (TTFB), and Content download. If Initial connection alone accounts for 220ms, getting the connection ready first is more helpful than adding another preload.
Further down, you need to prevent “writing it makes it slower”. The most common situation is too many preloads. The browser has a limited number of high-priority resources it can push simultaneously in the early phase. If a page already has 6 to 10 high-priority requests within the first 800ms, the above-the-fold image and font will have to wait in queue.
In the network waterfall chart, you’ll see queue congestion, staggered request starts, and fragmented download chunks. A page that originally had only HTML, CSS, above-the-fold image, and font—4 early requests—later adds a second carousel image, third carousel image, video cover, icon font, and chat script. It’s not uncommon for LCP to worsen by 200 to 600ms.
This set of situations most easily reverses optimization:
| Practice | Common Consequence | Quantified Impact |
|---|---|---|
| Preloading 5+ images | Above-the-fold bandwidth dispersed | LCP image start time actually delayed by 100 to 300ms |
| Preloading multiple font weights simultaneously | Font congestion | Above-the-fold text not necessarily earlier, adding 40 to 150KB upfront |
| Preloading non-above-the-fold CSS/JS | Competing for early connections | Longer above-the-fold request queue |
| Preloading wrong filename | Invalid download | Wasting an extra 50 to 300KB |
Above-the-fold image still has loading="lazy" |
Request scheduling conflict | Image start time often delayed by 200 to 500ms |
There’s another commonly overlooked issue: resources arrive early, but rendering doesn’t. For example, the above-the-fold image finishes downloading at 450ms, but the page is rendered on the client by a large frontend framework, with the main thread busy from 500ms to 1300ms, and the image node isn’t inserted into the DOM until 1.4s. The Network panel looks good, but LCP is still poor. Here, what you should check isn’t the preload tag, but script execution time, number of long tasks, and when above-the-fold components mount. If Long Tasks continuously appear in 3 to 5 segments, each lasting 80ms to 200ms, no amount of preloading will help much.
A common scenario: above-the-fold Hero image is 170KB, preloads and finishes downloading at 380ms; React or Vue above-the-fold module doesn’t finish hydration until 1.1s; final LCP still stalls at 2.6s. The network isn’t the problem—it’s that the element appears late.
Therefore, when testing, it’s best to look at both network and rendering together. Pages where LCP improves noticeably typically show two things simultaneously: LCP resource start time moves up by 200 to 500ms, and LCP element render time also shifts forward by 150 to 400ms. If only the former happens without the latter, there’s still a bottleneck in the rendering pipeline. This distinction is useful—it prevents you from continuing to add new tags in <head>.
You can organize verification results into a comparison table for easy reference:
| Metric | Expected Change | First Investigation if No Change |
|---|---|---|
| LCP Resource Start Time | Move up 150 to 500ms | Tag position, filename, cross-origin parameters |
| Priority | Become High or enter queue earlier | Whether as is correct |
| Initial Connection | Reduce by 80 to 250ms | Whether preconnect is missing |
| LCP Render Time | Move up 100 to 400ms | JS execution, hydration, DOM insertion timing |
| Console Warnings | Fewer unused preloads | Whether resources hit above-the-fold |
| Total Above-the-fold Requests | Kept to a minimum | Whether preloading is excessive |
There’s also version consistency. It’s common for builds to include hashed filenames, like hero.a1b2c3.webp, which changes with every deployment. Once the preload in the template isn’t updated along with it, the browser will download the old image first, then download the new one. The same applies to CSS files, especially split packages like home.9f8e7d.css and critical.1a2b3c.css.
After deployment, it’s best to do a real page capture to confirm that the preload URL in HTML exactly matches the actual request URL in the Network panel. Even one character difference can result in an extra 1 request + 80KB to 250KB of traffic during the above-the-fold phase.
Optimizing DNS Resolution
For each additional new domain name for critical rendering path resources, browsers typically need to perform an additional DNS lookup, a new connection establishment, and a TLS handshake. On desktop networks, the first resolution of a single domain typically adds 20–80ms, while on mobile networks it commonly adds 50–150ms. If LCP images, fonts, and CSS are distributed across 3 separate hostnames, the critical rendering path request startup time could be increased by 150–400ms. The optimization approach is straightforward: consolidate critical rendering path resources to 1–2 domains, only add preconnect or dns-prefetch for essential critical rendering path domains, and minimize the appearance of irrelevant third-party domains during the critical rendering path phase.
Reduce Above-the-Fold Domain Names
After many pages use CDN, resource download time may appear shorter, but LCP still doesn’t improve. The common cause is not that files are too large, but that the browser encounters too many new domain names during the above-the-fold phase. When users first open a page, after the browser gets the HTML, it needs to continue discovering where CSS, fonts, images, and scripts come from.
As long as there are 2 to 4 new hostnames in the above-the-fold content, the browser will perform several additional rounds of DNS lookups, TCP connections, and TLS handshakes. On desktop networks, a single new domain’s initial preparation typically adds 60–180ms; on mobile networks, reaching a total of 100–300ms is not uncommon. If the LCP image happens to be on a newly appearing hostname at the end, the download start time will be pushed back overall.
Let’s first look at a very common homepage resource distribution.
Main site HTML is on www.example.com, above-the-fold images are on img.examplecdn.com, CSS is on static.examplecdn.com, fonts are on fonts.example.net, and tracking scripts are on analytics.vendor.com. From a file management perspective, it’s clear, but looking at the browser’s work sequence in the first 500ms, things get more complicated. The browser doesn’t do less preparation just because these resources “all belong to the same brand site.” Each hostname needs to be handled separately. For a page targeting LCP under 2.5 seconds, adding 150–400ms for no reason at the beginning already has a noticeable impact.
Many teams first compress image size, such as reducing the above-the-fold image from 260KB to 180KB, or trimming CSS from 90KB to 65KB. Making files smaller is certainly helpful, but if the LCP image’s request start time is already 300ms late, the improvement from such compression is often less than reducing the number of above-the-fold domain names. Because users see “when does the largest content element appear on screen,” not “how many KB were saved during transmission.” As long as the request start is delayed, faster downloads just start on a later timeline.
You can first list the resources that actually participate in above-the-fold rendering, then see which hostnames they are distributed across. Most homepage top sections typically only depend on the following types of content:
-
The HTML document itself
-
1 LCP image, typically 120KB–350KB
-
1 above-the-fold CSS file, typically 20KB–80KB
-
1 set of above-the-fold fonts, if using external fonts
-
A small amount of immediately executing scripts, typically for navigation, accordion, or carousel controls
If these files are split across more than 4 domains, the browser’s early preparation time usually increases significantly. If they are concentrated on 1 to 2 domains, the above-the-fold request flow will be much shorter.
The following comparison makes it easier to see the problem:
| Above-the-Fold Resource Placement | New Domains in Above-the-Fold | Typical Prep Time | LCP Request Start |
|---|---|---|---|
| HTML, images, CSS mostly on same domain | 1 | 40–120ms | Earlier |
| Images, CSS, fonts each independent | 3 | 150–320ms | Later |
| Plus analytics, customer service, social media components | 5–7 | 250–600ms | Much Later |
Reducing hostname count during the above-the-fold phase is usually easier than continuing to split resource domains to get LCP earlier.
The browser’s reaction to “new domains” isn’t an abstract concept—it’s a specific sequence of work. Each new hostname often adds another round of DNS and connection preparation. If the page above only has one hero image, one heading, and a paragraph of text, but encounters 5 external domains within the first 600ms, the above-the-fold loading sequence is most likely not compact enough. Many times, the page isn’t “downloading too slowly,” it’s “starting requests too late.”
A more practical approach is to consolidate resources based on “what users can immediately see when they enter the page.” For example, if the above-the-fold only has a hero image and a button, a more reasonable combination is typically:
-
HTML and CSS on the main site or same static resource domain
-
LCP image and CSS should share the same CDN domain as much as possible
-
If fonts aren’t visually essential, prioritize system fonts
-
Scripts that only appear after above-the-fold shouldn’t be in the first 1 second of requests
After completing this set of adjustments, homepage above-the-fold often converges from 4 hostnames to 2. For many corporate sites, content sites, and service pages, this alone can advance the LCP request by 80–220ms.
Looking further, many pages split resources too finely not because it’s technically necessary, but because they follow old asset management practices. For example:
-
Images on
imgsubdomain -
CSS on
staticsubdomain -
JS on
jssubdomain -
Fonts on
fontssubdomain -
Video thumbnails on another media domain
This kind of separation was common in the HTTP/1.1 era, used to distribute connection pressure; but now many pages run on HTTP/2 or HTTP/3, so continuing to split into too many hostnames often yields little benefit, and the browser pays extra preparation time for each domain. If the server and CDN configuration allow, combining above-the-fold CSS, images, and some JS onto the same static domain is usually more appropriate.
The following scenarios make it easier to decide whether domains should be consolidated:
| Phenomenon | More Suitable Treatment |
|---|---|
| Above-the-fold only has 1 large image, but it’s from an independent image domain | Consolidate with above-the-fold CSS on the same static domain |
| Fonts only used for headings, but loaded from a third-party font service | Switch to self-hosted or system fonts |
| Very little above-the-fold JS, but using a dedicated script subdomain | Consolidate with static resource domain |
| CSS, images, SVG icons each from 3 different domains | Consolidate to 1–2 domains |
Some pages count font services as part of above-the-fold domains, which makes the problem even more obvious. External fonts typically don’t just bring one domain. Sometimes the font CSS is on fonts.provider.com, but the actual font files go to static.providercdn.com, meaning the browser has to handle 2 domains. If the text content in the top half of the page is small, or a system font alternative is acceptable, removing the external font service can typically reduce 1–2 connection preparations.
On pages where above-the-fold is dominated by images and buttons, users usually perceive a hero image appearing 200ms later more easily than subtle differences from switching headings to system fonts.
Let’s continue looking at third-party resources. Many homepages introduce simultaneously during the above-the-fold phase:
-
Analytics scripts
-
Session recording tools
-
Customer service components
-
Social media buttons
-
Video platform SDK
-
A/B testing scripts
Each of these brings 1 or more external hostnames. Even if they don’t participate in LCP, they occupy the browser’s early resources. If 4–6 third-party domains appear within the first 800ms above the fold, the LCP image’s priority is usually lowered. This type of page is more suitable for first doing “domain subtraction” rather than first doing “resource fine-tuning.”
You can use the following criteria to quickly determine if a page needs to reduce domains first:
-
Are resources in the visible above-the-fold area scattered across more than 3 new domains
-
Does the LCP image come from a newly appearing hostname
-
Are fonts from third parties, with font files on another CDN domain
-
Do customer service, analytics, social media, etc. domains appear within the first 500ms above the fold
-
Are above-the-fold CSS and images on different CDN hostnames
If 3 or more of these are “yes,” prioritizing domain consolidation is more worthwhile than continuing to compress images. Because on such pages, LCP often loses in early preparation, not in transmission volume. Sometimes a page doesn’t have much above-the-fold resources, but still uses multiple business subdomains. For example:
-
www.example.comserves HTML -
assets.example.comserves CSS -
media.example.comserves images -
fonts.example.comserves fonts
This structure is easy to differentiate for management purposes, but the browser doesn’t skip DNS, TCP, TLS just because they’re all under example.com. From a network layer perspective, they are still different hostnames. After consolidating assets and media into a single static domain, the above-the-fold preparation usually eliminates one full round of preparation. If a user’s RTT is around 80ms, this round of preparation is often worth over 100ms.
You also need to consider the real-world difference after cache hits. Some people say that on users’ second visit, DNS and connections can be reused, so having more domains doesn’t matter. But above-the-fold performance evaluation usually emphasizes first visits, slow network conditions, cross-region visits, and no-cache visits. In real user data, the proportion of first-time visitors arriving on the homepage, ad landing pages, and search result pages is often no less than 30%–70%. If a page builds its speed on the premise that “users have already cached multiple domains,” the homepage experience will be quite fragile.
Here’s an easier-to-execute organization method. Separate resources into “above-the-fold essential” and “can wait until after above-the-fold,” then map them to domains:
| Resource | Above-the-Fold Essential | More Appropriate Placement |
|---|---|---|
| LCP Image | Yes | Same domain as above-the-fold CSS |
| Above-the-Fold CSS | Yes | Main site or same static domain |
| Above-the-Fold Fonts | Depends on page | Self-hosted or system fonts |
| Analytics Scripts | No | Deferred loading |
| Customer Service Components | No | Load after user dwell time |
| Social Media/Video Scripts | No | Request after above-the-fold |
After completing this step, the above-the-fold request chain is usually much shorter. After the browser gets the HTML, it can discover above-the-fold resources faster and doesn’t need to prepare for too many new domains.
Many pages, after shrinking from 5 above-the-fold hostnames to 2, can advance the LCP image request time from 550ms to around 300ms. If the image volume is already small, this timing change is often more noticeable than continuing to compress formats.
You can also use waterfall charts to verify. If the HTML returns around 200ms and the LCP image is only 180KB, but doesn’t start requesting until 600ms, it’s probably not that the image downloads slowly. If during this 400ms you can see DNS Lookup, Initial connection, SSL, and there are multiple new domain requests in between, it means the number of above-the-fold domains is already affecting the resource start order. After removing unnecessary above-the-fold domains, check if the LCP image advances to 250–400ms, and the change will be very obvious.
For above-the-fold content, which domain resources are on often affects loading order more than which business module they belong to.
After the page completes this round of consolidation, then looking at preconnect, image compression, font subsetting, and caching strategies will be in a more reasonable order. Because the browser’s early preparation work has already been reduced, each subsequent optimization will be more easily reflected in real users’ above-the-fold times.
Only Use dns-prefetch and preconnect for Above-the-fold Essential Domains
After many pages integrate CDNs, LCP actually gets slower, not because resource downloads are slow, but because the browser spends extra time on DNS resolution, TCP connection, and TLS handshake before actually requesting resources. If 2 to 4 new domains appear in the above-the-fold content, the browser spends more time on preparations during the first few hundred milliseconds. On typical desktop networks, a single new domain’s DNS lookup takes about 20–80ms, with TCP+TLS adding another 40–150ms; on mobile networks, this phase can easily reach 100–300ms. So dns-prefetch and preconnect are not “more is safer”—they should only be used for domains that will be used immediately in the above-the-fold content, and wrong ordering can actually make the browser busier in the early phase.
Let’s first distinguish between the two tags. dns-prefetch only performs DNS resolution in advance, so the browser knows this domain and can look up the IP first; when the resource actually needs to load, it then establishes the connection. preconnect goes further, handling DNS, TCP, and TLS together. The cost and benefit differ for each.
If a domain hosts the LCP image, above-the-fold fonts, or above-the-fold API, preconnect is more suitable; if it’s only used after the above-the-fold content loads, such as comments, customer service, heatmaps, or recommendation modules, dns-prefetch is usually sufficient, or it can be omitted entirely.
The code is simple, but only include the domains that will be used “immediately”:
<link rel="dns-prefetch" href="//cdn.example.com">
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
The browser has limited connection resources available in the early phase. Many homepages write 6 to 10 preconnect tags in the <head> “just in case,” preconnecting image CDNs, font services, analytics scripts, customer service systems, A/B testing, and ad networks. As a result, during the first 300–800ms, the browser is busy establishing connections for many domains, while domains that actually participate in above-the-fold rendering aren’t getting faster. For pages with only 1 LCP image, 1 CSS file, and minimal text above the fold, preconnect count is usually better controlled at 1–3.
You can first categorize homepage resources into two groups based on “whether the above-the-fold content depends on it immediately”:
| Resource Type | Needed Immediately for Above-the-fold | More Suitable Hint Type | Common Count |
|---|---|---|---|
| LCP Image CDN | Yes | preconnect |
1 |
| Above-the-fold Font Domain | Depends on page | preconnect or omit |
0–1 |
| Above-the-fold API Domain | Depends on whether it blocks rendering | preconnect |
0–1 |
| Comment System | No | dns-prefetch or omit |
0–1 |
| Customer Service/Chat Tool | No | Omit or defer | 0–1 |
| Analytics/Heatmap/A/B Tools | No | dns-prefetch or defer |
1–3 |
The reason for this is simple. The browser has only a short window between receiving HTML and initiating the LCP resource request. If the page establishes connections for more than 5 domains at the start, the browser’s scheduling becomes more scattered. For users, what they see is that the above-the-fold hero image or first content appears 100–300ms later—they won’t feel the page is faster because the comment system was prepared in advance.
Determining which domains are “above-the-fold essential” shouldn’t be based solely on whether they’re important to the business, but whether they participate in above-the-fold rendering. Here’s a common scenario: the above-the-fold section includes a hero image, a headline, a subheading, and a button. What the browser will typically use first are:
- Main site HTML domain
- Domain where the LCP image is located
- Domain where above-the-fold CSS is located
- If above-the-fold text uses an external font, add the font domain
If both CSS and images are already on the same CDN domain, in the above-the-fold phase you often only need 1 preconnect. If fonts are locally hosted, you might only preconnect the image CDN domain, making the early page preparation lighter.
Here’s a comparison closer to real pages:
| Page Implementation | preconnect Count in head | New Domains in First 500ms | Common LCP Request Initiation Time Range |
|---|---|---|---|
| Only connect image CDN + above-the-fold fonts | 2 | 2–3 | 200–450ms |
| Connect images, fonts, analytics, customer service, ads | 6 | 5–7 | 400–800ms |
Many sites integrate Google Fonts, YouTube videos, HubSpot, Hotjar, Intercom, Meta Pixel, and A/B testing tools, making the head section quite busy. Each service comes from a different domain, so the browser spends the first few hundred milliseconds doing DNS, TCP, and TLS. As long as these domains aren’t actually needed for above-the-fold rendering, deferring them is usually more beneficial than “preconnecting everything.”
For example, the customer service widget typically appears 3–10 seconds after users enter the page, so competing for connections within the first 300ms of the page isn’t very useful.
Also note the side effects of preconnect. It establishes connections in advance, consuming browser socket and network resources. If a connection is established but not used for a long time, the browser sometimes closes it, or this preparation itself becomes wasted overhead. For example, if a page has preconnect for a font service, but the above-the-fold text ultimately uses a system font fallback, and the actual font file isn’t requested until 2 seconds later, then the earlier connection preparation has little benefit. Similarly, if an API is only triggered when the user scrolls or clicks, it shouldn’t be at the same priority as the LCP image.
For more practical prioritization, consider this checklist:
- Can the LCP image be discovered in the initial HTML content?
- Does above-the-fold CSS block above-the-fold layout?
- Will fonts change above-the-fold text size or line wrapping?
- Does API data affect above-the-fold main area content display?
- Will third-party scripts output user-visible content in the above-the-fold phase?
Only domains that answer “yes” to the first 4 items are closer to the appropriate use case for preconnect. If a domain only handles tracking, analytics, or session recording, it usually doesn’t have a hard dependency on above-the-fold rendering.
You can prioritize into a checklist:
- LCP image domain
- Above-the-fold CSS or blocking style resource domain
- Above-the-fold font domain (only prioritize if above-the-fold visuals depend on it)
- Above-the-fold API domain (only keep if HTML itself can’t get the content)
- Defer all other domains
After this treatment, the browser’s work in the first 1 second becomes simpler. For example, if the original homepage had 7 preconnect tags but only the image CDN truly participates in above-the-fold rendering, reducing to 2 often shifts the LCP request start point earlier by 80–200ms. If the original page also suffers from mobile networks and high RTT environments, the improvement can be even greater.
Now let’s look at dns-prefetch. Its cost is lower than preconnect—it doesn’t establish the entire connection like preconnect does—so it’s suitable for domains that “will be accessed soon but don’t block above-the-fold rendering.” For example, recommendation content APIs at the bottom of the page, comment domains, video platforms, and secondary image domains can all consider DNS prefetch only. In terms of benefit, dns-prefetch often only recovers 10–50ms of resolution time; but if the domain will be requested immediately after the above-the-fold section, this time is still useful.
For third-party services that don’t participate in above-the-fold rendering, you can also omit them entirely and let the browser request them at normal pace.
This table is easier to implement:
| Scenario | Recommendation | Reason |
|---|---|---|
LCP image comes from cdn.example.com |
preconnect |
Requested immediately above the fold, saves DNS+TCP+TLS |
| Body text uses external font with no system font fallback | preconnect |
Can reduce wait time before stable text rendering |
| Customer service loads 2 seconds later | Omit or defer script | Not visible in above-the-fold phase |
Bottom video comes from youtube-nocookie.com |
dns-prefetch or omit |
Doesn’t block top half display |
| Tracking, heatmap, A/B testing tools | dns-prefetch or defer |
No dependency on above-the-fold visible area |
Some teams ask: since preconnect has greater benefits, why not use it for everything? The answer lies in browser scheduling. If too many high-priority connections appear in the early phase, resources actually needed for above-the-fold rendering won’t necessarily get faster—instead, thread and network resources become more scattered. For pages with only 1 main visual, 1 stylesheet, and 1 font set above the fold, keeping 2 preconnect tags in the head is usually sufficient. Exceeding 3 should trigger a review of which domains can actually be downgraded to dns-prefetch or moved to later loading.
This should also be considered alongside font strategy. If the page uses external fonts, and the fonts come in three size tiers of 40KB, 80KB, 120KB with multiple font weights, the browser not only needs to preconnect to the font domain but also download the actual files.
In this situation, the more common optimization isn’t to add another preconnect, but rather to:
- Keep only 1–2 font weights needed for above-the-fold content
- Use
font-display: swap - Prefer local hosting of font files
- Avoid font CSS jumping to another new domain to fetch files
This way, above-the-fold text appears more stably, and you won’t consume too much early preparation time for a single font domain. If the above-the-fold content is mainly images and a few buttons, using system fonts is often sufficient, and you can even skip the font domain’s preconnect.
To verify if you’ve written it correctly, look at two points in the waterfall chart. First, before the LCP image request, has the image domain’s DNS and connection already been completed in advance? Second, at the start of the page, are there many connections “established early but not used yet”? If you see connections for customer service, ads, and analytics all established within 0–300ms, but the LCP image doesn’t start requesting until 500ms, the priority is wrong.
If after removing excess preconnect tags, the LCP image request moves up to 250–400ms, it means the browser’s early resource scheduling has become lighter.
Shortening the DNS Resolution Chain
Many pages experience slow LCP, not because CDN nodes download slowly, but because the browser spends extra time on DNS resolution before the resource request actually begins. When users first open a page, the browser needs to parse the HTML first, then discover which hostnames the images, CSS, fonts, and scripts are from. As long as the above-the-fold resources fall on 2 to 4 new domain names, the browser will add multiple rounds of DNS queries. On desktop networks, the first resolution of a single domain typically takes 20–80ms; on 4G or cross-region mobile networks, it’s commonly 60–150ms. If the LCP image domain itself has multiple layers of CNAME, the wait time continues to stack, causing the largest above-the-fold element to appear later.
Many sites, after adopting CDN, separate resources into img.example.com, static.example.com, fonts.example.com, and js.example.com. From a resource management perspective, this is clear, but from the browser’s timeline, it extends the preparation phase before rendering above-the-fold content. The browser won’t reuse DNS results just because these domains “belong to the same site.” Each new hostname requires a separate lookup.
Assuming the homepage above-the-fold depends on 3 first-appearing domains, with each domain consuming an additional 50ms, plus connection establishment and TLS, the LCP resource download start time could be delayed by 150–300ms. If the page’s goal is to keep LCP under 2.5 seconds, those extra hundred milliseconds are already enough to affect the score.
Going deeper, the problem is usually not just “too many domains,” but also “long resolution chains.” Some resource domains don’t reach edge nodes in one hop; instead, they go from the business domain, to the access domain, to the vendor’s scheduling domain, and only then to the actual node. The browser sees one domain name, but behind the scenes it actually traverses 2 to 4 layers of CNAME. The longer the resolution chain, the more unstable the first-visit time becomes.
When users access from different regions like North America, Western Europe, and Middle East, DNS response differences often stretch to 30–120ms. If local network quality is average, the difference becomes even larger, causing page performance to exhibit “sometimes fast, sometimes slow” behavior.
First, let’s look at the number of resource hostnames. For above-the-fold content, it’s not the total site requests that affect LCP first, but how many hostnames appear for the first time during the above-the-fold phase. LCP images, above-the-fold CSS, and above-the-fold fonts should be consolidated to 1 to 2 domains, making the browser’s early preparation much lighter. Many corporate sites, content sites, and service sites split images, styles, and fonts across 4 domains—the download process may not be faster, but the request start time is later. After consolidating images and CSS to the same CDN domain, it’s common to recover 80–200ms of upfront wait time.
You can check above-the-fold dependencies in this order:
- Which domain does the HTML come from, and does it match the main site
- Whether the LCP image is on a newly appearing hostname
- Whether above-the-fold CSS is on a different domain than the image
- Whether font files depend on a separate font domain
- Whether above-the-fold scripts introduce 2 or more third-party hostnames
If the homepage head already encounters 4 or more new domains within the first 500ms, the above-the-fold content is usually not lightweight. If the largest above-the-fold image doesn’t start requesting until after 400ms in the waterfall, prioritize looking at DNS and connection preparation, not image file size first.
When continuing the investigation, focus on CNAME layer count and DNS provider responses. Many teams only look at edge hit rates in the CDN vendor dashboard, ignoring the DNS resolution chain length. A hit rate of 95% or higher doesn’t guarantee early above-the-fold requests. If img.example.com first CNAMEs to img.cdn.vendor.net, then jumps to geo.vendor.net, and finally to the actual edge record, the resolution phase adds several steps. Different public resolvers also have varying response times, with common differences reaching 20–70ms. For pages with large images, this time may not seem dramatic; but if the LCP image itself is only 120KB–250KB, the proportion of DNS delay is quite significant.
A more reliable approach is to shorten the resolution chain for above-the-fold resource domains as much as possible:
- Consolidate above-the-fold image domains to within 1 to 2 layers of CNAME
- Don’t separate fonts to third-party font platforms; host them locally if possible
- Don’t assign separate hostnames for CSS, images, and scripts individually
- Reduce multi-hop structures like “business subdomain → access layer → scheduling layer → regional layer”
- For above-the-fold resources, prioritize DNS service providers with more stable global resolution performance
If the user distribution is dispersed, such as 40% in the United States, 30% in Europe, 20% in Southeast Asia, and the rest in Oceania and Middle East, it’s even more important to check whether global DNS responses are balanced. Some providers resolve quickly in a single region, but when accessing across continents, first-lookup times can be 50ms or higher. Page speed tests conducted in only one region easily miss this issue.
After domain count is controlled, the next step is to preconnect for domains that will actually participate in above-the-fold rendering. It’s important to distinguish between dns-prefetch and preconnect. The former only pre-performs DNS resolution, while the latter also prepares TCP and TLS. If the domain hosting the largest above-the-fold image must exist separately, it’s more suitable to add preconnect.
If it’s just a comment system, customer service plugin, or heatmap script, it typically doesn’t need to occupy above-the-fold connection resources. Keeping 1 to 3 preconnect entries in the homepage head is relatively stable; writing 5 or more, the browser often disperses the early connection resources.
For example, if the homepage above-the-fold needs:
- 1 main site domain
- 1 image CDN domain
- 1 font domain
The priority should usually be:
- Image CDN:
preconnect - Font domain:
preconnectonly if above-the-fold text immediately uses it - Other third parties: defer, or use
dns-prefetchonly
If customer service systems, ad networks, behavioral analytics, and social media components appear with 4 to 6 new domains within the first 1 second, the browser must allocate DNS, connection, and TLS resources first, pushing the LCP image to the back. Many pages aren’t slow at downloading—they’re slow at initiating requests. The most common signal in waterfall charts is: HTML returns around 200ms, LCP image is only 180KB, but actual download doesn’t start until after 600ms. The time gap in the first half is often spent on DNS, TCP, TLS, and resource discovery.
The following types of pages are more likely to have long resolution chains:
- Pages assembled with multiple SaaS tools, with above-the-fold third-party domains exceeding 5
- Images, CSS, JS, and fonts placed on separate subdomains
- Using external font services with 2 or more font weights
- CDN access layer is complex, with resource domains having 3 or more layers of CNAME
- Users distributed across 3 or more intercontinental regions with average DNS provider coverage
When encountering such pages, consider doing a round of consolidation first—compress above-the-fold resources discoverable in the first 14KB of HTML into fewer hostnames. As long as after parsing HTML, the browser can discover the LCP image address earlier, and that address doesn’t need to traverse a long DNS chain, the request start time will be earlier. In many cases, reducing above-the-fold domains from 4 to 2 improves above-the-fold perception more than compressing an image from 220KB to 160KB.
When investigating, checking the following points can speed up the process:
- How many new hostnames appeared in the first 500ms above-the-fold
- Whether the LCP image comes from a first-appearing external domain
- Whether resource domains have 2 or more layers of CNAME
- How much DNS Lookup occupies in the waterfall chart—is it over 50ms
- Whether fonts, analytics, and customer service simultaneously compete for early connections above-the-fold
- Whether
preconnectwas added for actual above-the-fold domains - Whether third-party scripts not involved in above-the-fold display were deferred to
DOMContentLoadedor later
You can also use a more actionable criterion for initial screening. If the homepage above-the-fold has only 1 large image, 1 CSS file, and minimal text, but LCP still exceeds 2.5 seconds, while TTFB is not high, then prioritize checking DNS. If the homepage has many requests but only 1 to 2 new above-the-fold domains, DNS is generally not the first thing to address. If above-the-fold resources are small and download is fast, yet requests are late, the issue is mostly with the preceding resolution chain and connection order.
After the page is modified, there are two locations where results are easiest to verify. One is the above-the-fold waterfall chart—confirm whether the LCP image request advanced from the original 500–700ms to 250–400ms. The other is real user data—observe whether P75 LCP across different regions recovered by 100–300ms.
If lab data improves but real user data shows no significant change, continue checking regional differences, public DNS response differences, and mobile network first-lookup times. Because on desktop broadband versus mobile networks, DNS resolution performance often differs by 1 times or more.
To make the page more stable, the above-the-fold phase is better suited with a “few domains, short chains, low interference” structure. When the browser first enters a page, where time is spent ultimately shows up in the LCP. If the DNS resolution chain is shortened, the LCP image typically enters the download phase earlier, and the largest above-the-fold element appears sooner.



