We inherited a marketing platform with a 4.8-second Largest Contentful Paint and a mobile Lighthouse score of 62. Twelve weeks later the same pages load their hero content in 1.1 seconds and score 98. This is exactly what we changed, in the order we changed it, with the measured impact of each step.
Where the time was actually going
Before touching any code we collected two weeks of field data from the Chrome UX Report and real-user monitoring. Synthetic Lighthouse runs are useful for debugging, but they are a terrible basis for prioritisation — our lab numbers were 40% more optimistic than what users on mid-range Android devices experienced.
The breakdown was unambiguous: 2.1 seconds of render-blocking JavaScript, 1.4 seconds of unoptimised hero imagery, and roughly 900ms of server response time caused by an uncached database query on every request.
Optimise what your users experience, not what your laptop experiences. The gap between the two is where most performance budgets quietly fail.
The seven changes that mattered
1. Server-side caching of the navigation query
A single recursive category query ran on every page render. Moving it behind a 60-second Redis cache with tag-based invalidation dropped Time To First Byte from 910ms to 120ms — the single largest win, achieved in under a day.
2. Route-level code splitting
The application shipped one 780KB JavaScript bundle to every route, including an analytics dashboard that 96% of visitors never opened. Dynamic imports at the route boundary reduced the marketing bundle to 148KB gzipped.
3. Proper image pipeline
Hero images were served as 2.4MB PNGs. Switching to AVIF with WebP fallback, correct sizes attributes and priority hints on the LCP element cut 1.3 seconds on mobile connections.
4. Self-hosted, subset fonts
Three font families loaded from a third-party CDN caused two extra connections and a 380ms delay. We subset to Latin, self-hosted with font-display: swap and preloaded only the single weight used above the fold.
5. Deferring third-party scripts
- Chat widget loaded on user interaction rather than page load
- Analytics moved to a server-side tagging endpoint
- Two abandoned marketing pixels removed entirely after an audit
6. Streaming server components
Converting the page shell to React Server Components with suspense boundaries let the hero render while personalised sections streamed in. First Contentful Paint improved by 620ms with no change in perceived completeness.
7. A performance budget enforced in CI
None of the above survives without automation. We added Lighthouse CI to the pipeline with hard thresholds: builds fail if the JavaScript bundle grows beyond 160KB or LCP regresses past 1.4 seconds in the lab profile.
What made no measurable difference
In the interest of honesty: HTTP/3, aggressive DNS prefetching and switching our CSS-in-JS library each produced changes within measurement noise. We reverted two of the three to keep the codebase simple.
Results after twelve weeks
LCP (75th percentile)
Lighthouse mobile
Signup conversion lift
Performance work is rarely one heroic refactor. It is a sequence of small, measured decisions — and the discipline to prevent regressions once you have won. If you want us to run the same audit on your platform, get in touch.
Lena Torres
Co-founder and CTO at AndNova. Distributed systems engineer, CNCF contributor, and a reluctant enthusiast for browser performance traces.