The Starting Point
The website loaded in 5.2 seconds according to Lighthouse. On mobile with 3G, it exceeded 12 seconds. Largest Contentful Paint was 4.8 seconds. All Core Web Vitals were in the red.
The Starting Point
The website loaded in 5.2 seconds according to Lighthouse. On mobile with 3G, it exceeded 12 seconds. Largest Contentful Paint was 4.8 seconds. All Core Web Vitals were in the red.
The client knew it was slow but didn’t know why. They had tried switching hosts without any meaningful improvement. They assumed they needed to rebuild the site from scratch.
That wasn’t necessary.
The Diagnosis
We analyzed the load waterfall and identified the culprits:
A 3.2 MB hero image in unoptimized PNG format.
Twelve different web fonts, some used in only one place.
Third-party JavaScript blocking rendering: analytics, a chat widget, an ad pixel, and three marketing scripts that were no longer in use.
No lazy loading on images below the fold.
CSS from a full framework when they were only using 8% of the styles.
Phase 1: Quick Wins
We converted images to WebP with appropriate compression. The hero image dropped from 3.2 MB to 89 KB. This single change reduced load time by 1.8 seconds.
We enabled lazy loading for images outside the initial viewport. Fewer resources needed to load before LCP.
We removed the outdated third-party scripts. Three of them weren’t even connected to active accounts.
Load time after Phase 1: 2.9 seconds. A 44% improvement.
Phase 2: Font Optimization
We reduced the font count from 12 to 3. The other nine were variations that could be handled with CSS or simply weren’t justified.
We implemented font-display: swap so text would appear immediately with system fonts while custom fonts loaded.
We added preload for the critical fonts used above the fold.
Load time after Phase 2: 1.8 seconds.
Phase 3: Critical JavaScript
We moved non-essential scripts to the end of the body with defer.
The chat widget now loads only after the user interacts with the page, not on initial load.
Analytics loads asynchronously without blocking anything.
Load time after Phase 3: 1.1 seconds.
Phase 4: Critical CSS
We extracted the CSS required for above-the-fold content and inlined it in the head.
The remaining CSS loads asynchronously after the initial render.
We removed unused CSS. The full framework weighed 180 KB; the actual required CSS weighed 23 KB.
Final load time: 0.52 seconds.
Business Impact
Mobile bounce rate dropped 31%.
Pages per session increased 18%.
Mobile conversions rose 24%.
The client reported that user complaints about slowness disappeared completely.
What We Learned
Most performance issues are the result of accumulated small decisions. No one added 5 seconds of load time all at once. It built up with every unoptimized image, every script added “just in case,” and every decorative font.
The solutions are usually mundane. Revolutionary technology isn’t required—only consistent application of basic discipline.
Hosting is rarely the problem. Switching hosts is the first thing many teams try, yet it’s almost never where the real issue lies.
From 5.2 seconds to 0.52 seconds. A 90% improvement without changing the design, migrating technology, or rebuilding anything from scratch.
Just systematically applying best practices that should have been in place from the beginning.
Performance isn’t magic. It’s attention to detail, constant measurement, and the willingness to remove anything that doesn’t add value.