Every 100ms of load time costs conversion rates. Every 1 second costs 7% of conversions. Here are the specific techniques we use to systematically cut load times in half — ordered by impact-to-effort ratio.
Performance optimisation is one of the highest-ROI engineering investments a product team can make. Google's research shows that going from 3 seconds to 1 second load time increases conversions by up to 27% for e-commerce. For SaaS, Amplitude's research found that every 1-second improvement in time-to-interactive correlates with a 10–15% increase in trial-to-paid conversion. This isn't a cosmetic concern — it's a revenue lever.
Before optimising anything, run Lighthouse on 3G Slow in Chrome DevTools. Look at your Core Web Vitals — LCP, CLS, and INP. Use the Network tab with cache disabled and CPU throttling at 4× to simulate real-world conditions. Optimise the biggest problems first.
1. Eliminate the Client-Side Waterfall
The single biggest load time improvement for most React SPAs is eliminating the client-side data waterfall. The classic pattern: browser downloads JS bundle → browser executes JS → component renders → component fires useEffect → API call is made → data arrives → page shows content. Every arrow is a round-trip or a blocking operation. In Next.js, move data fetching to Server Components and the waterfall collapses: server fetches data in parallel, renders HTML, streams it to the browser. The user sees content before any JS loads.
2. JavaScript Bundle Reduction
The average web app ships 1.2MB of JavaScript in 2026. Most of it is not needed for the initial render. Strategies that work: dynamic imports for routes (Next.js does this automatically), dynamic imports for heavy libraries (date-pickers, rich text editors, chart libraries), checking bundle size with @next/bundle-analyzer before every major dependency addition, and replacing heavy dependencies with lighter alternatives (day.js instead of moment, zod instead of yup for simple schemas).
// Bad — ships the entire chart library on initial load
import { LineChart } from 'recharts';
// Good — chart library only loads when the component is visible
const LineChart = dynamic(
() => import('recharts').then(mod => mod.LineChart),
{
loading: () => <ChartSkeleton />,
ssr: false,
}
);3. Image Optimisation: The Forgotten Wins
Images account for 60–70% of page weight on most marketing sites. The non-negotiables: serve WebP or AVIF (30–50% smaller than JPEG at same quality), always specify width and height attributes to prevent Cumulative Layout Shift, use loading='lazy' on below-fold images, and use a CDN with automatic format negotiation. Next.js Image component does all of this automatically. If you're not using it, you're leaving the easiest wins on the table.
4. Font Loading Strategy
Custom fonts cause Flash of Invisible Text (FOIT) and Flash of Unstyled Text (FOUT), both of which hurt LCP and CLS. The 2026 best practice: use next/font (or @font-face with font-display: optional), preload only the fonts needed for above-the-fold content, use a system font as fallback with size-adjust tuned to match your custom font's metrics, and host fonts on your own domain (third-party font loading adds a DNS lookup).
5. Database Query Optimisation
Slow API responses are often the real culprit behind slow load times, not the frontend. The diagnostic: add query timing middleware and log any query over 100ms. Common culprits: N+1 queries (loading a list, then making a separate query for each item — use SELECT with JOINs or ORM include), missing indexes on frequently queried columns, and SELECT * when you only need 3 columns (unnecessary data transfer across the wire).
We reduced one client's dashboard load from 4.2 seconds to 0.8 seconds. 90% of the gain came from two things: adding indexes on three columns, and eliminating an N+1 query that was firing 47 database queries on every page load.
6. HTTP/2 Push and Resource Hints
Modern CDNs support HTTP/2 and HTTP/3 automatically — make sure yours is enabled. Beyond that, use resource hints: preconnect to third-party origins you'll need (fonts, analytics, APIs), prefetch critical routes when the user hovers a link, and preload critical resources like your hero font or LCP image. These are metadata hints to the browser that cost nothing to ship and can shave 200–400ms off perceived load times.
7. Edge Caching and CDN Strategy
If your users are globally distributed and your server is in us-east-1, users in Mumbai are waiting 200ms just for the first byte — before any rendering happens. Cloudflare Workers or Vercel Edge Middleware can serve responses from the nearest edge node. For pages that don't change per-user (marketing pages, blog posts, public product pages), a CDN cache with stale-while-revalidate means returning users see cached pages in sub-50ms.
The Performance Monitoring Stack
Set up Vercel Speed Insights or Web Vitals tracking with the Next.js reportWebVitals hook. Connect it to your analytics to correlate performance with conversion. Set budget thresholds in CI — if a PR increases bundle size by more than 10KB or drops a Core Web Vitals score, the build fails. Performance budgets enforced automatically are the only performance budgets that hold.