Skip to content
All insights

Frontend

A Performance Budget That Survives Contact With the Design

By Vishnu · 17 February 2026 · 3 min read

Photograph by William Warby on Unsplash

Performance work usually happens in the wrong order. A site is built, someone runs Lighthouse a fortnight before launch, the score is disappointing, and a sprint gets spent clawing back milliseconds from decisions made months earlier.

The decisions that determined the score were made months earlier. That is the whole problem.

A budget is a number with an owner

"The site should be fast" is not a budget. A budget is a specific number, attached to a specific metric, that something fails against.

Largest Contentful Paint under 2.5 seconds on a mid-range Android over 4G. Total Blocking Time under 200 milliseconds. Cumulative Layout Shift under 0.1. Total JavaScript under a stated size, uncompressed, because compressed size hides how much the device still has to parse and execute.

Those numbers need to exist before the design is finished, because they change what gets designed. A full-bleed autoplaying hero video and a 2.5-second LCP on a mid-range phone are not both achievable, and that is a conversation worth having at the wireframe stage rather than the week before launch.

The score is not the experience

Lighthouse is a lab test on a simulated device, and it is useful precisely because it is repeatable. It is not what your users experience.

Field data — real devices, real networks, real geography — routinely diverges from the lab. A site scoring 95 in a lab on a fast connection can be miserable on a four-year-old Android in an area with poor coverage, which for a great many businesses describes a substantial share of their traffic.

Use the lab number as a regression check, because it is stable and cheap. Use field data to decide what to work on, because it is the truth. Teams that optimise purely for the lab score end up gaming a benchmark.

The main thread is usually the problem

Most poor scores in modern applications are not download time. Bandwidth has improved considerably; single-core CPU performance on mid-range phones has improved much less.

A large JavaScript bundle costs twice — once to transfer, then again to parse, compile and execute, and that second cost lands on the main thread while the user is looking at an unresponsive page. A heavy dependency that arrives quickly on a fast connection can still block interaction for seconds on the device where it matters.

Which is why the useful questions during a build are how much of this bundle is needed for first render, what can be deferred until after the page is interactive, and whether the heavy thing needs to be on the critical path at all. Deferring an expensive component until after load, rather than shrinking it, is frequently the larger win.

Reserve the space

Layout shift is the cheapest of these to fix and the most persistently neglected. Every image, embed, advertisement and dynamically loaded component needs its space reserved before it arrives.

It is also the failure users notice most, because it does not merely feel slow — it makes them tap the wrong thing. A mis-tap caused by a shifting layout is a worse experience than an extra second of loading, and it converts worse too.

Cache like you mean it

Static assets that never change under a given name should be served with a long, immutable cache lifetime. This is well understood and still frequently misconfigured, particularly where a hosting platform applies its own defaults over the application's.

The trap is that "immutable for a year" is a promise: it means replacing that asset requires changing its filename. A team that updates a file in place and expects visitors to see the change will find they do not, sometimes for a very long time. Content-hashed filenames exist to make this safe, and they are worth using for anything large.

Automate it or lose it

A budget checked manually is a budget that will be exceeded. The check belongs in the pipeline, failing a build when the bundle grows past its limit or the score drops below its floor.

This sounds strict and mostly it just relocates an argument. Instead of discovering after launch that the site got slower, a specific change gets to explain why it is worth the budget it consumed. Sometimes the answer is that it is worth it and the budget should move. That is a fine outcome — it was a decision, made deliberately, by someone who knew the cost.


iLeaf builds web and mobile products where performance is a requirement rather than a post-launch project — see Product Engineering.

Thinking about this for your own business?

We have been building and running enterprise systems since 2011. Talk to a solutions lead about where agents pay off first.

Talk to a solutions lead