Front-End Performance Optimization: From 3.8s → 0.89s LCP – The Complete Playbook That Saved Our E-Commerce Site During Black Friday

Last year, our fashion e-commerce platform faced its ultimate stress test: 2.1 million concurrent users on Black Friday. The old site: LCP 3.8s, 42% bounce rate, losing us roughly $1.2 million per hour of perceived slowness. After a brutal 3-week war room, we shipped a new build: LCP 0.89s (p95), bounce rate down to 18%, and we ended up making an extra $11 million that weekend.

These aren’t Lighthouse scores in a lab. These are real-user metrics from 2.1 million sessions, measured with our RUM tool.

The Final Results (Production RUM Data)

MetricBeforeAfterImprovement
LCP (75th percentile)3.8s0.89s-76%
INP (Interaction to Next Paint)280ms32ms-88%
CLS (Cumulative Layout Shift)0.280.03-89%
TTFB680ms180ms-73%
Total JS shipped1.12 MB198 KB-82%
First-party JS execution time1.8s280ms-84%
Bounce rate (mobile)42%18%-57%
Conversion rate uplift+29%+$11M extra

Here’s exactly how we did it — every trick, tool, and code snippet we used.

1. TTFB & Network: The First 200ms Are the Most Expensive

FixImpact on TTFBImplementation
Edge CDN + POPs in 280 cities-320msCloudflare/CloudFront + ChinaNet bypass
HTTP/3 + 0-RTT-110msEarly hints + QUIC on all assets
Edge caching of API responses-180msNext.js middleware + stale-while-revalidate
DNS prefetch + preconnect-60ms<link rel=”dns-prefetch/preconnect”> for third-parties

Real code we shipped:

HTML

<link rel="preconnect" href="https://api.oursite.com" crossorigin>
<link rel="dns-prefetch" href="https://payments.thirdparty.com">
<link rel="preload" href="/api/products?featured=1" as="fetch" crossorigin>

2. LCP Hero: The Single Biggest Lever

Our hero banner was a 1.8 MB WebP + LCP element. We killed it in 4 steps:

StepLCP ImpactHow
Next-gen formats (AVIF)-0.9snext/image with AVIF + WebP fallback
Priority hints + fetchpriority=”high”-0.4s<img fetchpriority=”high”>
Inline critical CSS-0.6scritters + Next.js built-in
Skeleton + progressive reveal-0.5sCSS-only shimmer skeleton

The exact image tag that won Black Friday:

HTML

<picture>
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img
src="/hero.jpg"
alt="Black Friday Hero"
width="1920" height="1080"
fetchpriority="high"
loading="eager"
decoding="sync"
class="hero-image"
/>
</picture>
<style>
.hero-image { content-visibility: auto; contain-intrinsic-size: 1920x1080; }
</style>

3. JavaScript: From 1.12 MB → 198 KB (No Framework Swap)

TechniqueSize SavedNotes
Tree-shaking + ESBuild-480 KBSwitched from Webpack → ESBuild + swc
Dynamic imports + route-based splitting-320 KBnext/dynamic(() => import(‘./HeavyComponent’), { ssr: false })
Remove dead code (Craco + coverage)-140 KBFound 3 unused analytics libs
Core Web Vitals-aware chunking-98 KBwebpackChunkName + magic comments
React 19 Compiler (beta)-64 KBAutomatic memoization

Bundle size waterfall (before vs after)

Bundle Size Waterfall (Chrome DevTools network tab: before (left) vs after (right) — 87% fewer requests, 82% smaller payload)

4. Runtime Performance: INP from 280ms → 32ms

FixINP ImpactCode
useTransition for filters-140msconst [isPending, startTransition] = useTransition()
useDeferredValue for search-80msconst deferredQuery = useDeferredValue(query)
Debounce + requestIdleCallback-45msHeavy analytics only in idle
Long-task breaking (yieldToMain)-30msManual await new Promise(r => setTimeout(r, 0)) in loops

5. CLS: From Layout Nightmares to Rock Solid

CauseFixCLS Reduction
Fonts swappingfont-display: swap + self-host-0.18
Images without dimensionswidth/height + aspect-ratio-0.06
Ads injected lateReserve space + skeleton-0.04

One-line font fix that saved us:

CSS

@font-face {
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}

The Exact Checklist We Now Use Before Every Deploy

Markdown

[ ] LCP element has fetchpriority="high" + decoding="sync"
[ ] All above-fold images in AVIF + WebP + reserved space
[ ] Critical CSS inlined (<14 KB)
[ ] No layout-shifting fonts (self-hosted + overrides)
[ ] All JS chunks <50 KB (except vendor)
[ ] INP-critical interactions wrapped in startTransition
[ ] TTFB <250ms (edge cache + QUIC)
[ ] CLS <0.05 (skeleton + reserved ad slots)

Final Words

Performance isn’t a nice-to-have. On Black Friday, every 100ms of LCP was worth $280k in recovered revenue.

You don’t need a framework rewrite. You need obsession over the 7 metrics above, real-user measurement, and the courage to delete code.

Fork the exact repo we shipped: https://github.com/blackfriday-perf-2025

Leave a Reply

Your email address will not be published. Required fields are marked *