Back to blog
PerformanceJanuary 1, 2024· 5 min read

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:

  1. Code splitting
  2. Tree shaking
  3. Lazy loading
  4. 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:

  1. Smaller images
  2. Less JavaScript
  3. Simpler CSS
  4. 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:

  1. What users see first (FCP, LCP)
  2. When they can interact (TTI, TBT)
  3. 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.