What is pre-connection?
A preconnect is a resource hint that tells the browser to establish an active HTTP connection to a domain that the browser has not yet determined to be established. Creating an HTTP connection requires many steps, including:
Do a DNS lookup.
Connect to TCP.
Negotiate secure TLS connections.
This can take tens or even hundreds of milliseconds. Pre-connecting improves performance because when the browser does realize that it needs to establish a connection to download the resource, that connection has already happened!
How to use preconnect to improve performance
Given the impressive gains above, I know what you must be thinking:
If pre-connecting resource hints improves overall performance and user experience, why don’t I pre-connect to all domains used by my website?
Unfortunately, this hurts performance. Why? It’s simple: browsers use a lot of complex logic to decide what needs to be downloaded and when, so pages can render and respond to visitors as quickly as possible. (If you want all the nerdy details, Pat Meenan has documented and demonstrated it exhaustively.)
Sites that use resource hints are essentially asking to override what the browser would normally do. This can be the source of different performance issues if not used carefully.
Too many preconnect prompts
Browsers limit the number of HTTP connections they will maintain. Using too many preconnected resource hints will limit the browser to the connections it needs. In fact, too much preconnect can hurt performance.
A good rule of thumb is no more than 6-8 pre-connected resource hints.
Pre-connect to an unused domain
The only thing worse than doing too many preconnects is asking the browser to preconnect to a domain that isn’t even used! However, this can be very common. Sites change the source of their content, or stop using third-party providers without removing prompts for pre-connected resources for that domain. Pre-connecting to an unused domain can cause performance problems in two ways:
Unused preconnects hurt browsers because they block connections to other domains.
Open TCP and encrypted TLS connections use server resources even when not in use. Akamai research found that up to 6% of encrypted HTTP connections don’t actually make any requests.
prematurely closed preconnect
Because browsers limit the number of HTTP connections they will keep, if no request occurs for 10 seconds, the browser will close the HTTP connection. Premature Preconnect occurs when a preconnect prompt tells the browser to open an HTTP connection to a domain, but no request is sent to that domain within 10 seconds. The browser then closes this connection and only needs to connect again if it needs to request resources from that domain. This is bad for two reasons:
Premature preconnect can harm browsers because it blocks connections to other domains.
Once a request for that domain is actually encountered, the browser must open another connection to that domain. So there is no net gain at all to pre-connect!
Safari’s rel resource prompt problem
Many sites have adopted a pattern of specifying both the preconnect hint and the dns-prefetch hint within the same <link> tag, as shown below. (For a detailed discussion, see our guide to DNS prefetching resource hints.)
This practice started because browsers support different types of resource hints. As of 2020, there are more browsers that support preconnect than those that support DNS prefetch, and all major browsers that support DNS prefetch also support preconnect.
There’s really no benefit to specifying two different resource hints within the same <link> tag, and in fact, doing so has a huge downside. Safari only allows specifying a resource hint in the rel attribute of the <link> tag. Specifying both hints in the same rel attribute causes Safari to skip the <link> tag entirely and not try either resource hint.
In fact, specifying multiple resource hints disables Safari’s hints! Instead, you should just use the <link> hint.
When to use the preconnect prompt
Typically, preconnect hints should be provided for:
Fields later found in waterfalls
Domains with resources critical to page rendering or interaction
Domains with heavy requests or downloads
Good examples include:
Additional domains with CSS and JS bundles required in the critical rendering path
Web fonts are referenced by CSS and need to be downloaded
The first-party domain of the API endpoint used to initially load or render the page
Once you have determined which domains should be preconnected, you still need to test them! Just because something should improve your site’s performance or experience, doesn’t mean it will. Make sure to always test to verify:
Use tools to measure your performance.
Implement your changes.
Compare “before” and “after” performance metrics.
Best Practices for Preconnecting Resource Hints
We’ve seen many benefits of using pre-connected resource hints, but there are also many pitfalls that can impact performance if used incorrectly. This means it’s important to review how your page uses resource hints to make sure you’re following all best practices.
First, identify any preconnected resource hints that the page is currently using. You will need to look for the <link> tag in the base HTML page, as well as link: HTTP headers that can also contain resource hints. Also keep in mind that link headers containing resource hints can appear in other responses than the base HTML page!
Using the guidelines above, determine which domains should be preconnected. Are they in the list of hints the page already uses? If not, why not?
Are you using more than 6-8 preconnects? If so, there are too many and you should consider removing them.
Next, for each preconnected domain, verify that a request was sent to it and that the request happened within 10 seconds to avoid prematurely closing the connection. Most waterfall charts will allow you to filter by domain or partial URL as shown below. This makes it easier to see if and when a request is happening in the domain.
Finally, review each resource hint and make sure there are not multiple hints in the <link> tag.