In 2006, Amazon reported that every 100ms of latency cost them 1% in sales. In 2012, Google found that a 400ms delay reduced searches by 0.44%. In 2017, Akamai found that a two-second delay in web page load time increased bounce rates by 103%. The numbers shift slightly with each study, but the direction never does.
We are building in 2026. The average mobile page still takes 8.6 seconds to become interactive. The average desktop page ships 2.4MB of JavaScript. These are not technical problems. They are prioritisation problems.
The three budgets
Performance work becomes tractable when you think in budgets. There are three that matter: the loading budget, the scripting budget, and the rendering budget. Each has different levers and different failure modes.
The loading budget is about bytes over the wire. Images, fonts, JavaScript, CSS. The question is not 'how fast is our server?' but 'how much are we asking the user to download before they can do anything?' The answer, for most sites, is too much.
Performance is not a feature. It is the substrate on which every other feature depends.
JavaScript is the most expensive resource
A 100KB image and a 100KB JavaScript file are not equivalent. The image is decoded once. The JavaScript is parsed, compiled, and executed — and then it runs again every time the user interacts with the page. The cost is not the download. The cost is the processing.
On a mid-range Android device — which represents the median global user — parsing 1MB of JavaScript takes approximately 2.5 seconds. This is before a single line of your application logic runs. This is the tax you pay for shipping a framework, a state management library, a date utility, and three analytics SDKs.
# Install
npm install --save-dev source-map-explorer
# Build with source maps
npm run build -- --sourcemap
# Analyse
npx source-map-explorer dist/assets/*.js
# What you're looking for:
# - Any single dependency > 50KB (gzipped)
# - Duplicate packages at different versions
# - Polyfills for features you don't needThe rendering budget
The rendering budget is about what happens after the JavaScript runs. Layout thrashing — reading and writing to the DOM in alternating calls — is the most common cause of janky animations and slow interactions. The browser can't batch its work if you keep interrupting it.
The fix is architectural. Read all your DOM measurements first. Then write all your DOM mutations. Never interleave them. This is not a micro-optimisation. On complex interfaces, this single change can reduce interaction latency by 60%.
Core Web Vitals as a design constraint
Google's Core Web Vitals — LCP, INP, CLS — are not just SEO signals. They are a useful forcing function for performance discipline. LCP (Largest Contentful Paint) asks: how long until the user sees the most important thing? INP (Interaction to Next Paint) asks: how long until the user's action produces a response? CLS (Cumulative Layout Shift) asks: does the page jump around while loading?
We use these as design constraints from the beginning of a project, not as metrics to optimise at the end. The LCP element is identified in the design phase. The font loading strategy is decided before a line of code is written. The image dimensions are specified in the design file so the browser can reserve space before the image loads.
Performance is not a feature you add. It is a discipline you maintain. The cost of a second is not abstract. It is measured in users who left, conversions that didn't happen, and trust that wasn't built.