Connection hints
dns-prefetch, preconnect and preload links the document declares.
At a glance the headline numbers for Connection hints
dns-prefetch, preconnect and preload links the document declares.
Connection hints on the typical site: 0 dns-prefetch, 0 preconnect, 0 preload.
Distribution & median CLS site count and median CLS at each level of connection hints — dns prefetch
Passing CLS by connection hints — dns prefetch which level passes the CLS most often
Connection hints — dns prefetch 0. p75 1. p99 8. At the low end (0–0): CLS 0.00. At the high end (2+): CLS 0.00. computed
Distribution & median CLS site count and median CLS at each level of connection hints — preconnect
Passing CLS by connection hints — preconnect which level passes the CLS most often
Connection hints — preconnect 0. p75 1. p99 6. At the low end (0–0): CLS 0.00. At the high end (2+): CLS 0.00. computed
Distribution & median CLS site count and median CLS at each level of connection hints — preload
Passing CLS by connection hints — preload which level passes the CLS most often
Connection hints — preload 0. p75 1. p99 18. At the low end (0–0): CLS 0.00. At the high end (4+): CLS 0.00. computed
Why this matters for the Core Web Vitals, and where to start fixing it
Hints move network work earlier. dns-prefetch resolves a domain name before it is needed. preconnect goes further and completes the TCP and TLS setup too. preload fetches one specific file that the scanner would otherwise find late, like a background hero image or a critical font.
Hints are easy to overuse. Every preconnect spends sockets and CPU on a connection you might never use. A preload that is not critical steals bandwidth from something that is. A handful of deliberate hints beats a wall of them.
Chrome field data from 189,915 sites, representing millions of real page loads. How we measured.
Live queries (6) — admin only
SELECT COUNT(*) AS count,
quantile_disc(m.resource_hints.connection_hints.dns_prefetch, 0.10) AS p10,
quantile_disc(m.resource_hints.connection_hints.dns_prefetch, 0.25) AS p25,
quantile_disc(m.resource_hints.connection_hints.dns_prefetch, 0.50) AS p50,
quantile_disc(m.resource_hints.connection_hints.dns_prefetch, 0.75) AS p75,
quantile_disc(m.resource_hints.connection_hints.dns_prefetch, 0.90) AS p90,
quantile_disc(m.resource_hints.connection_hints.dns_prefetch, 0.99) AS p99
FROM sites WHERE m.resource_hints.connection_hints.dns_prefetch IS NOT NULL;
SELECT CASE WHEN m.resource_hints.connection_hints.dns_prefetch >= 0 AND m.resource_hints.connection_hints.dns_prefetch < 1 THEN 0 WHEN m.resource_hints.connection_hints.dns_prefetch >= 1 AND m.resource_hints.connection_hints.dns_prefetch < 2 THEN 1 WHEN m.resource_hints.connection_hints.dns_prefetch >= 2 THEN 2 END AS bucket_idx, COUNT(*) AS n,
quantile_disc(crux."phone".cls, 0.5) AS median,
COUNT(*) FILTER (WHERE crux."phone".cls IS NOT NULL AND crux."phone".cls <= 0.1) * 1.0 / NULLIF(COUNT(*) FILTER (WHERE crux."phone".cls IS NOT NULL), 0) AS good_pct
FROM sites WHERE m.resource_hints.connection_hints.dns_prefetch IS NOT NULL GROUP BY bucket_idx;
SELECT COUNT(*) AS count,
quantile_disc(m.resource_hints.connection_hints.preconnect, 0.10) AS p10,
quantile_disc(m.resource_hints.connection_hints.preconnect, 0.25) AS p25,
quantile_disc(m.resource_hints.connection_hints.preconnect, 0.50) AS p50,
quantile_disc(m.resource_hints.connection_hints.preconnect, 0.75) AS p75,
quantile_disc(m.resource_hints.connection_hints.preconnect, 0.90) AS p90,
quantile_disc(m.resource_hints.connection_hints.preconnect, 0.99) AS p99
FROM sites WHERE m.resource_hints.connection_hints.preconnect IS NOT NULL;
SELECT CASE WHEN m.resource_hints.connection_hints.preconnect >= 0 AND m.resource_hints.connection_hints.preconnect < 1 THEN 0 WHEN m.resource_hints.connection_hints.preconnect >= 1 AND m.resource_hints.connection_hints.preconnect < 2 THEN 1 WHEN m.resource_hints.connection_hints.preconnect >= 2 THEN 2 END AS bucket_idx, COUNT(*) AS n,
quantile_disc(crux."phone".cls, 0.5) AS median,
COUNT(*) FILTER (WHERE crux."phone".cls IS NOT NULL AND crux."phone".cls <= 0.1) * 1.0 / NULLIF(COUNT(*) FILTER (WHERE crux."phone".cls IS NOT NULL), 0) AS good_pct
FROM sites WHERE m.resource_hints.connection_hints.preconnect IS NOT NULL GROUP BY bucket_idx;
SELECT COUNT(*) AS count,
quantile_disc(m.resource_hints.connection_hints.preload, 0.10) AS p10,
quantile_disc(m.resource_hints.connection_hints.preload, 0.25) AS p25,
quantile_disc(m.resource_hints.connection_hints.preload, 0.50) AS p50,
quantile_disc(m.resource_hints.connection_hints.preload, 0.75) AS p75,
quantile_disc(m.resource_hints.connection_hints.preload, 0.90) AS p90,
quantile_disc(m.resource_hints.connection_hints.preload, 0.99) AS p99
FROM sites WHERE m.resource_hints.connection_hints.preload IS NOT NULL;
SELECT CASE WHEN m.resource_hints.connection_hints.preload >= 0 AND m.resource_hints.connection_hints.preload < 1 THEN 0 WHEN m.resource_hints.connection_hints.preload >= 1 AND m.resource_hints.connection_hints.preload < 2 THEN 1 WHEN m.resource_hints.connection_hints.preload >= 2 AND m.resource_hints.connection_hints.preload < 3 THEN 2 WHEN m.resource_hints.connection_hints.preload >= 3 AND m.resource_hints.connection_hints.preload < 4 THEN 3 WHEN m.resource_hints.connection_hints.preload >= 4 THEN 4 END AS bucket_idx, COUNT(*) AS n,
quantile_disc(crux."phone".cls, 0.5) AS median,
COUNT(*) FILTER (WHERE crux."phone".cls IS NOT NULL AND crux."phone".cls <= 0.1) * 1.0 / NULLIF(COUNT(*) FILTER (WHERE crux."phone".cls IS NOT NULL), 0) AS good_pct
FROM sites WHERE m.resource_hints.connection_hints.preload IS NOT NULL GROUP BY bucket_idx;