đź…­

What to <link rel=dns-prefetch> and when to use preconnect

The dns-prefetch resource hint is intended to look-up domain names before the browser would otherwise know that they’d be needed in the near future. It’s a quick way to speed up the loading of external page resources.

DNS-prefetching is such an easy performance optimization to make that it’s been included on one in five websites. As many as one in five of the top 500 000 websites deploy DNS-prefetching. Admittedly, a huge portion of this figure comes from WordPress defaults. (Figures from a crawl of HTTPS websites in the Tranco list on .)

I’ll start by discussing how this mechanism works and how it’s commonly misapplied. I’ll then move on to discuss the preconnect resource-hint and then discuss browser support.

The following example instructs the web browser to resolve an example domain name and store it in its cache:

<link rel="dns-prefetch"
     href="//example.net/">

It makes no difference if you use a protocol-relative URL (as shown above), or an absolute URL. The browser extracts the domain name by parsing the URL.

Different web browsers and operating systems have different DNS-caching policies. We can assume that a resolved domain name will remain cached for at least one minute in the average web browser.

DNS is cached in the browser, operating system, your edge gateway (“router”), and by your upstream recursive DNS resolver (often your ISP). It’s easy to get confused about your performance testing results unless you’re testing with different domain names each time.

So, which domain names should be pre-resolved? Many online tutorials recommend resolving the domain names of all the external stylesheets, scripts, frames, and images included in the document. This is unnecessary.

Browsers go through documents as they’re loaded and start to resolve domain names and establish connections to all the domains that their document preload scanners find. This includes URLs in iframe img, link, script, and other such elements.

DNS-prefetching is, however, useful for domain names that the browser’s pre-processor can’t possibly know about at the time it starts to render the document. Any external resources that are required by a frame, script, or stylesheet are prime candidates.

For example, an ad network may be embedded in your webpage as <script src="https://example.com/">. You don’t need to prefetch this domain name. However, that script then tries to fetch a resource from https://example.org/. That’s the domain name that will benefit from being DNS-prefetching.

Your browser can’t infer that it will need to connect to this second domain from analyzing the current document. You should only DNS-prefetch domains that meet the following requirements:

  • The domain is a chained dependency not already loaded by the webpage itself.
  • The domain is expected to be required within one minute of the document being loaded.

Priming the DNS cache can save anywhere from a few milliseconds to seconds on a high-latency connection. However, you can save hundreds of milliseconds to tens of seconds by not only priming the DNS cache but also establish a connection to the required host early.

The following example instructs the web browser to resolve an example domain name, set up a TCP connection to it, and complete the TLS handshake. The connection will be ready when the browser wants to fetch resources from it later.

<link rel="preconnect"
     href="https://example.net/">

Note the use of an absolute URL.

You don’t need to use DNS prefetch when you’re using preconnect. The domain name will be resolved as the first step of the browser establishing the connection.

Browsers will close unused connections much quicker than DNS entries expire from their caches. Chrome gives a warning if the connection remains unused ten seconds after it was opened. The requirements for which domains to preconnect to are slightly different than for dns-prefetch:

  • The domain is a chained dependency not already loaded by the webpage itself.
  • The domain is expected to be required within ten seconds of the document being loaded.

So, what’s browser support like for dns-prefetch, preconnect, and both resource hints?

DNS-prefetching has been widely supported since the beginning of . Preconnect has been supported since the middle of . The following table shows the current state of feature support in the market-leading browsers as of the time of publication:

Browser support for resource-hint link relationships
dns-prefetch dns-prefetch preconnect preconnect
Safari 13 (iOS) No Yes
Safari 13 (MacOS) Yes No Yes
Firefox 71+ HTTP-origins only No
Firefox 70 HTTP-origins only Yes
Tor Browser 9 No
Brave 1 Yes
Chromium 78
Vivaldi 2.9

As discussed earlier, DNS-prefetching is redundant when using preconnect. It can be used in combination with preconnecting to cater to older browsers that don’t support preconnect.

Unfortunately, Safari/WebKit assumes that the rel attribute only contains a single value. (The attribute is meant to support a list of space-separated values, like the class attribute.) Websites hoping to improve compatibility end up breaking the feature in Safari instead.

Safari on iOS never implemented DNS-prefetching. Preconnect is supported from iOS 11.2 () onward.

DNS-prefetching is only available in Firefox for webpages loaded over HTTP. This practically means that Firefox doesn’t support it at all. HTTPS is the default protocol for the web these days. I’ve opened a bug to address this issue. You can follow bug #1596935 for updates.

Update (): I published this article right before the release of Firefox 71, so I completely missed that preconnect stopped working in the very next version! It still doesn’t work today in Firefox 81.

Firefox’s behavior seems to have been caused by a misunderstanding of Chrome’s behavior. Chromium published a design document that discussed how it had implemented DNS prefetching. Unfortunately, it discusses a different but related technology in the same document. This other technology is disabled on HTTPS for privacy reasons but that behavior didn’t apply for the manual dns-prefetch resource hint.

Tor Browser inherits Firefox’s refusal to resolve DNS-prefetch resource-hints on HTTPS websites. Additionally, a separate problem keeps it from resolving any such hints, even on HTTP websites. The Tor Browser talks to the Tor Onion routing-anonymizing network over a SOCKS5 proxy. Neither Firefox nor Tor Browser supports DNS-prefetching or preconnecting over SOCKS5 proxies.

Networking in the Tor Browser is greatly complicated by its use of the Tor Onion routing-anonymizing network. The browser’s use of the Onion routing system means connections gets encrypted in layers and bounce from proxy-relay to proxy-relay.

The cost of establishing a connection over the Tor Onion routing-anonymizing network is higher than over a regular network connection. The Tor Browser could see a significant performance boost from supporting the preconnect resource hint.

Conclusions

You will get better results from preconnect than dns-prefetch. DNS-prefetching is only a small part of the work required to establish a network connection. Both are pointless if you load resources directly from the same domain. Use the requirements suggested earlier in the article as a checklist.

You can include dns-prefetch for backward-compatibility. Browsers have supported it for more than ten years. You’ll need to include it in a separate <link> element to cater to WebKit.

You can also use dns-prefetch for things that you’re not going to need right away but will need within one minute.

Be aware that DNS is cached in many places. Be sure to account for that in your performance testing.

The Tor Browser, arguably the browser that would benefit the most, supports neither preconnect nor dns-prefetch. Reducing your dependency on external hosts is always going to be the best path to higher performance across the board.

Update (): Quick update to say that nothing has changed! Neither Firefox version 100 nor Safari version 15.4 has addressed any of the issues discussed in this article.