Search code examples
google-chromeweb-performancepreconnect

Is there a limit to how many domains we should "dns-prefetch preconnect" with Chrome?


When we want to make sure a blazing fast website who uses third-party widgets/plugins/add-ons/analytics etc.. One of the many requirements to achieve this is to "dns-prefetch preconnect" for each individual domain name (basically saving a little for the DNS lookups etc.)

I could not find a document that would advise how many domain names we could "dns-prefetch preconnect" before we lose any potential benefit. Remember how in the old times Internet Explorer had a limit to how many images could be downloaded in parallel, just wonder if Chrome could have some reasoning for limiting "dns-prefetch preconnect" request?

For example: how many is too many?

<link rel="dns-prefetch preconnect" href="https://admin.typeform.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://api.amplitude.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://api.segment.io" crossorigin />
<link rel="dns-prefetch preconnect" href="https://app.launchdarkly.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://bam.nr-data.net" crossorigin />
<link rel="dns-prefetch preconnect" href="https://cdn.amplitude.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://cdn.segment.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://customer.api.drift.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://embed.typeform.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://event.api.drift.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://events.launchdarkly.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://fonts.googleapis.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://images.typeform.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://js-agent.newrelic.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://js.driftt.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://load.sumo.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://metrics.api.drift.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://renderer-assets.typeform.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://static.addtoany.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://sumo.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://weclean1.typeform.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://www.google-analytics.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://www.googletagmanager.com" crossorigin />
<link rel="dns-prefetch preconnect" href="https://www.youtube.com" crossorigin />

Any links feedback/advice is greatly appreciated!


Solution

  • 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:

    1. decide which metrics matter to you and your users
    2. use the best available synthetic and real-user numbers to measure the status quo
    3. 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 with rel="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.