Website Performance Metrics: What Actually Matters
A practical Fusebox guide to website performance metrics.
Website Performance Metrics: What Actually Matters
Published: January 2024
Reading time: 8 minutes
Users leave slow sites. Google ranks fast sites higher. But which metrics actually matter? Here's what to measure and why.
The Metrics That Matter
1. First Contentful Paint (FCP)
What: When first text/image appears Good: < 1.8 seconds Poor: > 3.0 seconds
// Measure FCP
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name === 'first-contentful-paint') {
console.log('FCP:', entry.startTime);
}
}
}).observe({ entryTypes: ['paint'] });
Why it matters: Users see progress
2. Largest Contentful Paint (LCP)
What: When main content loads Good: < 2.5 seconds Poor: > 4.0 seconds
Common LCP elements:
- Hero images
- Video posters
- Large text blocks
- Background images
Real example:
News site: Hero image is LCP (2.8s) ⚠️
Fix: Preload image, optimize size
Result: LCP drops to 1.9s ✓
3. Time to Interactive (TTI)
What: When page responds to input Good: < 3.8 seconds Poor: > 7.3 seconds
The frustration metric:
- Page looks ready
- User clicks button
- Nothing happens
- User rage-clicks
- Bad experience
4. Total Blocking Time (TBT)
What: How long page is frozen Good: < 200ms Poor: > 600ms
What causes blocking:
// Bad: Blocks for 500ms
for (let i = 0; i < 1000000; i++) {
document.querySelector('.item-' + i);
}
// Good: Breaks up work
function processItems(items, index = 0) {
const chunk = items.slice(index, index + 100);
// Process chunk
if (index < items.length) {
requestIdleCallback(() => processItems(items, index + 100));
}
}
5. Cumulative Layout Shift (CLS)
What: How much stuff moves Good: < 0.1 Poor: > 0.25
Common culprits:
- Images without dimensions
- Ads loading late
- Fonts changing
- Dynamic content
Fix example:
<!-- Bad: Causes layout shift -->
<img src="hero.jpg">
<!-- Good: Reserves space -->
<img src="hero.jpg" width="800" height="400">
Real-World Performance Problems
Problem 1: JavaScript Bloat
Symptoms:
main.js: 2.5MB (850KB gzipped)
Parse time: 1.2s
Execute time: 800ms
Impact: 2 seconds before page is interactive
Solutions:
- Code splitting
- Tree shaking
- Lazy loading
- Remove unused code
Problem 2: Render-Blocking Resources
Network waterfall shows:
HTML |==|
wait...
CSS |====|
wait...
JS |======|
wait...
First Paint X (3.5s)
Fix:
<!-- Preload critical resources -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="font.woff2" as="font" crossorigin>
<!-- Defer non-critical -->
<script defer src="app.js"></script>
Problem 3: Third-Party Scripts
Actual measurement from e-commerce site:
Your code: 500KB, 400ms
Google Analytics: 45KB, 200ms
Facebook Pixel: 75KB, 350ms
Chat widget: 180KB, 600ms
Ad network: 450KB, 1200ms
Reviews widget: 220KB, 800ms
Total third-party: 3.35 seconds!
Measuring Performance
1. Browser DevTools
Chrome Lighthouse:
Performance Score: 78
- FCP: 1.8s ✓
- LCP: 3.2s ⚠️
- TBT: 450ms ⚠️
- CLS: 0.05 ✓
Performance Tab:
- Record page load
- See timeline
- Find bottlenecks
- Profile JavaScript
2. Real User Monitoring (RUM)
// Capture real user metrics
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Send to analytics
analytics.track('performance', {
metric: entry.name,
value: entry.startTime,
url: window.location.href
});
}
});
observer.observe({ entryTypes: ['paint', 'largest-contentful-paint'] });
3. Web Vitals Library
import { getCLS, getFID, getLCP } from 'web-vitals';
getCLS(console.log); // Cumulative Layout Shift
getFID(console.log); // First Input Delay
getLCP(console.log); // Largest Contentful Paint
Performance Budget
Setting Targets
Fast site targets:
JavaScript: < 200KB (compressed)
CSS: < 50KB
Images: < 500KB (above fold)
Total requests: < 50
Load time: < 3 seconds
Monitor continuously:
{
"budgets": [{
"resourceTypes": ["script"],
"budget": 200
}, {
"resourceTypes": ["image"],
"budget": 500
}, {
"resourceTypes": ["total"],
"budget": 1000
}]
}
Quick Wins
1. Image Optimization
Before:
hero.png: 2.5MB
product1.jpg: 800KB
product2.jpg: 750KB
After:
hero.webp: 250KB (90% smaller!)
product1.webp: 80KB
product2.webp: 75KB
Implementation:
<picture>
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg" alt="Hero" width="1200" height="600">
</picture>
2. Resource Hints
<!-- DNS prefetch for external domains -->
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<!-- Preconnect for critical origins -->
<link rel="preconnect" href="https://api.example.com">
<!-- Preload critical resources -->
<link rel="preload" href="critical.css" as="style">
<!-- Prefetch next page -->
<link rel="prefetch" href="/next-page.html">
3. Font Loading
/* Prevent layout shift from fonts */
@font-face {
font-family: 'MyFont';
src: url('font.woff2') format('woff2');
font-display: swap; /* Show fallback immediately */
}
4. Lazy Loading
<!-- Native lazy loading -->
<img src="product.jpg" loading="lazy" alt="Product">
<!-- Intersection Observer for custom -->
<div class="lazy-section" data-src="heavy-component.js"></div>
Performance by Device
Mobile Considerations
3G Connection Reality:
Download: 1.6 Mbps
Latency: 300ms
CPU: 4x slower than desktop
Your 2MB page:
- Desktop (fiber): 1.5s
- Mobile (3G): 12s 😱
Mobile-first optimization:
- Smaller images
- Less JavaScript
- Simpler CSS
- Fewer requests
Testing Different Conditions
// Simulate slow network
await page.emulateNetworkConditions({
offline: false,
downloadThroughput: 1.6 * 1024 * 1024 / 8, // 1.6 Mbps
uploadThroughput: 750 * 1024 / 8,
latency: 300
});
Common Performance Myths
Myth 1: "CDN Solves Everything"
Reality: CDN helps with static assets, not slow code
Myth 2: "Users Have Fast Internet"
Reality:
- Mobile users: Often on 3G/4G
- Global users: Varying speeds
- Coffee shops: Shared bandwidth
Myth 3: "Caching Fixes Performance"
Reality: First visit still matters for:
- New users
- Social media traffic
- Search traffic
Performance Checklist
Before Launch
- Images optimized and lazy loaded
- CSS/JS minified and compressed
- Critical CSS inlined
- Resource hints added
- Third parties audited
- Performance budget set
Monitoring
- RUM tracking enabled
- Alerts for slowdowns
- Regular Lighthouse audits
- Competitor benchmarking
- User feedback tracked
Quick Audit
- Run Lighthouse
- Check network waterfall
- Test on slow 3G
- Measure all Core Web Vitals
- Profile JavaScript execution
Tools for Performance
Testing Tools
- Lighthouse: Overall audit
- WebPageTest: Detailed analysis
- PageSpeed Insights: Real-world data
Monitoring
- Google Analytics: Core Web Vitals
- SpeedCurve: Continuous monitoring
- Calibre: Performance tracking
Development
- Webpack Bundle Analyzer: Find bloat
- Chrome DevTools: Profile and debug
- Lighthouse CI: Automated testing
The Business Impact
Real Numbers
- Amazon: 100ms slower = 1% less revenue
- Google: 500ms slower = 20% less traffic
- Walmart: 1s faster = 2% more conversions
Your Impact
Before optimization:
- Load time: 5.2s
- Bounce rate: 45%
- Conversions: 1.2%
After optimization:
- Load time: 2.1s
- Bounce rate: 28%
- Conversions: 2.1%
Result: 75% increase in conversions!
The Bottom Line
Performance is user experience. Focus on:
- What users see first (FCP, LCP)
- When they can interact (TTI, TBT)
- Visual stability (CLS)
Measure, optimize, repeat. Fast sites win.
Monitor performance metrics instantly: Fusebox tracks Core Web Vitals and performance metrics in real-time while you browse. $29 one-time purchase.