Open in app Sign up Sign in
Search
A Netflix Web Performance Case Study
Improving Time-To-Interactive for Netflix.com on Desktop
Addy Osmani · Follow
Published in Dev Channel
7 min read · Nov 5, 2018
Listen Share
tl;dr: There are no silver bullets to web performance. Simple static pages benefit
from being server-rendered with minimal JavaScript. Libraries can provide great
value for complex pages when used with care.
Netflix is one of the most popular video streaming services. Since launching globally
in 2016, the company has found that many new users are not only signing up on
mobile devices but are also using less-than-ideal connections to do so.
By refining the JavaScript used for Netflix.com’s sign-up process and using
prefetching techniques, the developer team was able to provide a better user
experience for both mobile and desktop users and offer several improvements.
Loading and Time-to-Interactive decreased by 50% (for the logged-out desktop
homepage at Netflix.com)
JavaScript bundle size reduced by 200kB by switching from React and other
client-side libraries to vanilla JavaScript. React was still used server-side.
Prefetching HTML, CSS and JavaScript (React) reduced Time-to-Interactive by
30% for future navigations
Reducing Time-to-Interactive by shipping less JavaScript
The area optimized for performance by the Netflix developers was the logged-out
homepage, where users come to sign-up or sign-in to the site.
The Netflix.com homepage for new and logged-out members
This page initially contained 300kB of JavaScript, some of which was React and other
client-side code (such as utility libraries like Lodash), and some of which was
context data required to hydrate React’s state.
All of Netflix’s webpages are served by server-side rendered React, serving the
generated HTML and then serving the client-side application, so it was important to
keep the structure of the newly-optimized homepage similar to maintain a
consistent developer experience.
Homepage tabs are an example of a component initially written using React
Using Chrome’s DevTools and Lighthouse to simulate the logged-out homepage page
being loaded on a 3G connection showed that the logged-out homepage took 7
seconds to load, far too long for just a simple landing page, so the potential for
improvement was investigated. With some performance auditing, Netflix discovered
their client-side JS had a high cost.
Network throttling for the unoptimized Netflix.com in Chrome DevTools
By turning off JavaScript in the browser and observing which elements of the site
still functioned, the developer team could determine if React was truly necessary for
the logged-out homepage to function.
Since most of the elements on the page were basic HTML, remaining elements such
as JavaScript click handling and class adding could be replaced with plain
JavaScript, and the page’s language switcher, originally built using React, was rebuilt
in vanilla JavaScript using less than 300 lines of code.
The complete list of components ported to vanilla JavaScript were:
Basic interactions (tabs halfway down the homepage)
Language switcher
Cookie banner (for non-US visitors)
Client-side logging for analytics
Performance measurement and logging
Ad attribution pixel bootstrap code (which are sandboxed in an iFrame for
security)
Even though React’s initial footprint was just 45kB, removing React, several libraries
and the corresponding app code from the client-side reduced the total amount of
JavaScript by over 200kB, causing an over-50% reduction in Netflix’s Time-to-
Interactivity for the logged-out homepage.
Payload comparison before and after removing client-side React, Lodash and other libraries.
In a lab environment, we can validate users can now interact with the Netflix
homepage quickly using Lighthouse (trace). Desktop TTI is < 3.5s.
Lighthouse report after the Time-to-Interactive optimizations were made
What about metrics from the field? Using the Chrome User Experience report we
can see First Input Delay — the time from when a user first interacts with your site
to the time when the browser is actually able to respond to that interaction — is fast
for 97% of Netflix users on desktop. This is great.
First Input Delay (FID) measures the delay users experience when interacting with the page.
Prefetching React for subsequent pages
To further improve performance when navigating their logged-out homepage,
Netflix utilized the time spent by users on the landing page to prefetch resources for
the next page users were likely to land on.
This was achieved by using two techniques — the built-in <link rel=prefetch>
browser API and XHR prefetching.
The built-in browser API consists of a simple link tag within the head tag of the
page. It suggests to the browser that the resource (e.g. HTML, JS, CSS, images) can
be prefetched, though it doesn’t guarantee that the browser actually will prefetch the
resource, and it lacks full support from other browsers.
Comparison of prefetching techniques
XHR prefetching, on the other hand, has been a browser standard for many years
and produced a 95% success rate when the Netflix team prompted the browser to
cache a resource. While XHR prefetching cannot be used to prefetch HTML
documents, it was used by Netflix to prefetch the JavaScript and CSS bundle for
subsequent pages.
Note: Netflix’s HTTP response header configuration is preventing HTML caching
with XHR (they do no-cache on the second page’s HTML). Link Prefetch is otherwise
working as expected because it will work on HTML even if no-cache is present up to
a certain point.
// create a new XHR request
const xhrRequest = new XMLHttpRequest();
// open the request for the resource to "prefetch"
xhrRequest.open('GET', '../bundle.js', true);
// fire!
xhrRequest.send();
By using both the built-in browser API and XHR to prefetch HTML, CSS, and JS, the
Time-to-Interactive was reduced by 30%. This implementation also required no
JavaScript to be rewritten and didn’t negatively impact the performance of the
logged-out homepage, and hence offered a valuable tool for improving page
performance at a very low-risk.
After prefetching was implemented, the Netflix developers observed improvements
by analyzing reductions in the Time-to-Interactive metric on the page, as well as
using Chrome’s developer tools to directly measure cache hits of resources.
Netflix logged-out homepage — optimization summary
By prefetching resources and optimizing the client-side code on Netflix’s logged-out
homepage, Netflix was able to greatly improve their Time-to-Interactive metrics
during the sign-up process. By prefetching future pages using the built-in browser
API and XHR prefetching, Netflix was able to reduce Time-to-Interactive by 30%.
This was for the second-page loading, which contained the bootstrapping code for
single-page app sign-up flow.
The code optimizations carried out by the Netflix team showed that while React is a
useful library, it may not provide an adequate solution to every problem. By
removing React from the client-side code on the first landing page for signup, the
Time-to-Interactive was improved by over 50%. Reducing Time-to-Interactive on the
client-side also caused users to click the sign-up button at a greater rate, showing
that code optimization can lead to a greater user experience overall.
While Netflix didn’t use React for the homepage, they prefetched it for subsequent
pages. This allowed them to leverage client-side React throughout the rest of the
single page application sign-up process.
For more details on these optimisations, see this A+ talk by Tony Edwards:
Netflix JavaScript Talks - Performance Signup in React & Transactional A…
A…
Conclusion
Netflix discovered opportunities to improve their Time-to-Interactive by keeping a
close eye on the cost of JavaScript. To discover if your site has opportunities to do
better here, consult your performance tools.
The tradeoff Netflix decided to make is to server-render the landing page using
React, but also pre-fetching React / the code for the rest of the signup flow while on
it. This optimizes first load performance, but also optimizes the time to load for the
rest of the signup flow, which has a much larger JS bundle size to download since it’s
a single-page app.
Consider if leveraging vanilla JavaScript is an option for flows in your site. If you
absolutely need to use libraries, try to only ship down down code your users will
need. Techniques like prefetching can help improve page load times for future page
navigations.
Additional notes
Netflix considered using Preact, however, for a simple page flow with low
interactivity, using vanilla JavaScript was a simpler choice for their stack.
Netflix experimented with Service Workers for static resource caching. At the
time, Safari didn’t support the API (it now does) but they’re exploring them again
now. The Netflix sign-up flow needs more legacy browser support than the
member experience. Many users will sign-up on an older browser, but watch
Netflix on their native mobile app or a TV device.
The Netflix landing page is quite dynamic. It’s their most heavily A/B tested page
in the sign-up flow, with machine learning models used to customize messaging
and imagery depending on location, device type and many other factors. With
almost 200 countries supported, there are different localization, legal and value
messaging challenges for each derivative. For more on A/B testing, see Testing
Into A Better User Experience by Ryan Burgess.
With thanks to Netflix UI Engineers, Tony Edwards, Ryan Burgess, Brian Holt, Jem Young,
Kristofer Baxter (Google), Nicole Sullivan (Chrome) and Houssein Djirdeh (Chrome) for
their reviews and contributions.
JavaScript Web Performance React Performance Web
Follow
Written by Addy Osmani
86K Followers · Editor for Dev Channel
Head of Google Chrome Developer Experience
More from Addy Osmani and Dev Channel
Addy Osmani in Google Developers
Exploring EcmaScript Decorators
Iterators, generators and array comprehensions; The similarities between JavaScript and
Python continue to increase over time and I for one…
Jul 9, 2015 11K 36
Paul Kinlan in Dev Channel
Detect if your Native app is installed from your web site
As the capabilities of the Web become more aligned with what was once the domain of native
experiences there are an increasing number of…
Jul 26, 2017 481 6
Sam Dutton in Dev Channel
How to add full text search to your website
Many types of website need efficient, accurate search.
Feb 9, 2018 1.2K 5
Addy Osmani
Chrome now shows each active tab’s memory usage!
In Chrome Canary, we recently introduced hover cards that show the memory usage for each
open tab!
Oct 4, 2023 287 3
See all from Addy Osmani
See all from Dev Channel
Recommended from Medium
Alexander Nguyen in Level Up Coding
The resume that got a software engineer a $300,000 job at Google.
1-page. Well-formatted.
Jun 1 24K 483
Melody Koh 🤔 in Prototypr
The UX job market REALLY sucks right now
Why you should pivot and change directions right NOW
Aug 22 4.3K 39
Lists
Stories to Help You Grow as a Software Developer
19 stories · 1441 saves
General Coding Knowledge
20 stories · 1674 saves
A Guide to Choosing, Planning, and Achieving Personal Goals
13 stories · 2096 saves
Medium's Huge List of Publications Accepting Submissions
334 stories · 3773 saves
Peter Shanosky
Gen Z is Disillusioned With Our Economy and Society. They Should Be.
An ode and apology to my successors.
Mar 12 2K 38
Aaron Dinin, PhD in Entrepreneurship Handbook
How Bad Entrepreneurs Reveal Themselves in the First 5 Seconds of a
Pitch
A few simple words is all it takes to figure out a founder’s odds of startup success.
Sep 26 5.3K 157
Shuai Li in Programming Domain
Can You Answer This Senior Level JavaScript Promise Interview
Question?
Most interviewees failed on it.
Aug 12 3.3K 34
Abi
I shut down my startup. Here’s the honest truth.
Today, I’m announcing Zencape Health’s shutdown. After four years, two major pivots,
countless experiments, tens of thousands in annual…
Oct 15 6.3K 148
See more recommendations