Web Development

How We Reduced a Client's Page Load Time from 8s to Under 1s

A
Admin
· Jan 23, 2026 · 3 min read
How We Reduced a Client's Page Load Time from 8s to Under 1s

The Problem

A client came to us with a serious problem: their Laravel e-commerce website was taking 7-9 seconds to load on a standard broadband connection. Their bounce rate was over 70%, and their Google PageSpeed score was a dismal 18/100 on mobile.

They were losing customers every single day. Here's exactly how we fixed it.

Step 1: Diagnosis

Before touching a single line of code, we ran a thorough diagnosis using:

  • Google PageSpeed Insights — Identified LCP, FID, and CLS issues
  • WebPageTest — Waterfall analysis showing which resources were blocking render
  • Laravel Debugbar — Revealed 847 database queries on the homepage alone
  • Chrome DevTools Network tab — Found 4.2MB of uncompressed images

The culprits were clear: N+1 query problems, massive unoptimized images, no caching, and a 2.1MB JavaScript bundle loaded synchronously.

Step 2: Fixing the N+1 Query Problem

The homepage was loading products, then for each product loading its category, brand, and reviews separately. 847 queries became 6 with eager loading:


// Before: 847 queries
$products = Product::all();
// In the view: $product->category->name (N+1!)

// After: 6 queries
$products = Product::with(['category', 'brand', 'reviews' => fn($q) => $q->latest()->limit(3)])
    ->where('is_active', true)
    ->paginate(24);

This single change reduced server response time from 4.2s to 0.8s.

Step 3: Image Optimization

The site had product images up to 4000×4000px being displayed at 300×300px. We:

  • Converted all images to WebP format (average 65% size reduction)
  • Implemented responsive images with srcset
  • Added lazy loading to all below-the-fold images
  • Set up automatic image resizing on upload using Laravel's Intervention Image

Total image payload reduced from 4.2MB to 380KB.

Step 4: Caching Strategy

We implemented a multi-layer caching strategy:

  • Route cachingphp artisan route:cache reduced routing overhead
  • Config cachingphp artisan config:cache
  • View caching — Compiled Blade templates cached
  • Redis query caching — Homepage data cached for 5 minutes
  • HTTP caching headers — Static assets cached for 1 year in browser

Step 5: JavaScript and CSS Optimization

The 2.1MB JavaScript bundle was loaded synchronously in the <head>, blocking all rendering. We:

  • Moved scripts to the bottom of <body> with defer
  • Code-split the bundle — only load what's needed per page
  • Removed 14 unused jQuery plugins (legacy code)
  • Minified and compressed all CSS and JS
  • Inlined critical CSS to eliminate render-blocking stylesheets

JavaScript bundle: 2.1MB → 340KB. CSS: 890KB → 78KB.

Step 6: Server Configuration

  • Enabled Gzip/Brotli compression on Nginx
  • Configured PHP OPcache for bytecode caching
  • Set up a CDN (Cloudflare) for static asset delivery
  • Upgraded PHP from 7.4 to 8.3 (significant performance improvement)

The Results

MetricBeforeAfter
Page Load Time8.2s0.87s
Database Queries8476
Page Size7.1MB820KB
PageSpeed (Mobile)1891
Bounce Rate71%34%
Conversion Rate0.8%2.3%

Key Takeaways

  1. Always profile before optimizing — you can't fix what you can't measure
  2. Database query optimization usually has the highest ROI
  3. Images are almost always the biggest performance culprit
  4. Caching is not optional for production applications
  5. Every 100ms of load time improvement measurably impacts conversion rates

Is your website slow? We offer free performance audits. Get in touch and let's see what we can do.

Have a Project in Mind?

Let's build something extraordinary together. Start with a free consultation.


Warning: Module "mysqli" is already loaded in Unknown on line 0