Is there a limit to how many domains we should "dns-prefetch preconnect" with Chrome?
Resource hints shouldn't be over-used
First, as mentioned below, you should prefer preload
. If you don't know exactly what resources your page will include, the dns-prefetch
and preconnect
can be appropriate.
The resource hint specification indicates that the optimal number of connections is highly contingent:
The optimal number of connections per origin is dependent on the negotiated protocol, users current connectivity profile, available device resources, global connection limits, and other context specific variables. As a result, the decision for how many connections should be opened is deferred to the user agent.
Both dns-prefetch
and preconnect
indicate the user agent "should" initiate the process, which means they don't have to do so.
Ilya Grigorik, the editor of that spec, says
That said, use it wisely: each open socket incurs costs both on the client and server, and you want to avoid opening sockets that might go unused. As always, apply, measure real-world impact, and iterate to get the best performance mileage from this feature.
Sérgio Gomes, also a Googler, echos Ilya's warning with a bit more specificity:
Bear in mind that while
<link rel="preconnect">
is pretty cheap, it can still take up valuable CPU time, particularly on secure connections. This is especially bad if the connection isn’t used within 10 seconds, as the browser closes it, wasting all of that early connection work.In general, try to use
<link rel="preload">
wherever you can, as it’s a more comprehensive performance tweak, but do keep<link rel="preconnect">
in your toolbelt for the edge cases.
Sérgio continues to illustrate a couple examples where preconnect
, rather than preload
, is appropriate. I highly recommend taking a look at those.
Ivan Akulov, former Googler and current web performance startup CEO, ventures a numerical recommendation:
You want to speed up more than 4-6 domains. It’s not recommended to use
<link rel="preconnect" />
with more than 4-6 domains, as opening and keeping a connection is an expensive operation.<link rel="dns-prefetch" />
is more lightweight, so use it for other third-party domains if you want to speed them up too.
But Ivan, though a reputable source, doesn't provide hard technical support for this recommendation.
Without reading the source code for each relevant browser, it's impossible to defensibly say how many dns-prefetch/preconnects are too many. Even after reading source code, it can only offer a hint as to how many are appropriate. There is no hard limit, but the authoritative sources above give us reason to be cautious.
But it's difficult to know where to draw the line
There's only one way to improve performance:
- decide which metrics matter to you and your users
- use the best available synthetic and real-user numbers to measure the status quo
- make changes and measure the difference
It would take a number of iterations to land on the best possible configuration. And the optimal hint selection could change over time. From a maintainability perspective, it would be best to aggressively preconnect everything that meets Sérgio's "edge case" requirements, and trust the browser to do its job. But again, never without testing.
A couple other notes
That's a lot of third-party dependencies for that page. I'm sure you're working within your requirements, but this may be a great time to ask management to re-evaluate the necessity of some of those.
Finally, keep in mind that crossorigin
isn't appropriate for every resource hint. It depends on whether the resource(s) to be downloaded will use CORS. If you don't know, that could double the number of preconnects needed.
The
crossorigin
attribute, when used withrel="preconnect"
, doesn't describe where the target origin is but rather what kind of assets will be downloaded from that origin. If the assets use CORS,crossorigin
is needed. If CORS won't be used,crossorigin
should be omitted. If both types of assets will be present, two resource hints are necessary.
Take a look at this list of resources that use CORS for guidance.
Also be aware of this bug if you care about Safari:
https://web.dev/preconnect-and-dns-prefetch/
Browser support for dns-prefetch is slightly different from preconnect support, so dns-prefetch can serve as a fallback for browsers that don't support preconnect.
<link rel="preconnect" href="http://example.com"> <link rel="dns-prefetch" href="http://example.com">
Recommended — To safely implement the fallback technique use separate link tags.
<link rel="preconnect dns-prefetch" href="http://example.com">
Not recommended — Implementing dns-prefetch fallback in the same tag causes a bug in Safari where preconnect gets cancelled.
There was a limit of six concurrent DNS lookups in older Chrome versions. As of Chrome version 26 for Windows, Mac, and Linux, there is an asynchronous DNS resolver, which effectively removed that limit (or perhaps just increased it):
"6 DNS requests is no longer true with async DNS resolver, but your point still stands.. we limit number of inflight resolves." — Ilya Grigorik, Web performance engineer at Google (via Twitter)