Skip to content

1.1 — Why performance pays

Module 1 · Lesson 1 · 🟢 Foundational · ~20 min

What you'll learn

  • The causal mechanisms linking speed to revenue (not just correlations)
  • What published commerce case studies actually claim, and how to read them honestly
  • How to measure your own conversion elasticity instead of borrowing someone else's number
  • How to write a performance business case that survives a finance review

Why this lesson is first

Performance work fails for organizational reasons far more often than technical ones. The technique in Module 6 is not hard. Getting six weeks of engineering time to apply it, and getting marketing to remove a tag, requires a number that a VP believes.

This lesson gives you that number — and teaches you not to fake it.


The causal mechanisms

Speed doesn't magically increase conversion. Four concrete mechanisms do the work:

1. Abandonment before first paint. Users leave during the blank screen. This is the dominant effect on entry pages over slow connections, and it's why LCP correlates so strongly with bounce on Home/PLP/PDP. It's also invisible in your funnel analytics: a user who bounced at 6 s never fired a page‑view event in some setups, so your data understates the problem.

2. Perceived quality → trust. Commerce runs on trust. A page that jumps around while loading, or a checkout that takes 400 ms to respond to a tap, reads as "sketchy" — measurably so in usability studies. This is the main mechanism on checkout, where users have already committed and won't bounce over 200 ms, but will abandon a form that feels broken.

3. Interaction friction compounds. Product discovery is a many‑interaction flow. If each filter toggle costs 400 ms of jank, a shopper who would have applied five filters applies two, sees worse results, and buys less. INP damage shows up as fewer items viewed per session, not as a bounce.

4. Crawl budget and ranking. Core Web Vitals are a (small) ranking signal, but the bigger effect for a 2.4M‑SKU catalog is crawl efficiency: a slow TTFB directly reduces how many product pages get crawled per day, which affects long‑tail indexation and therefore organic traffic.

Mechanism matters because it tells you which metric to fight on which page. Bounce‑driven pages → LCP. Discovery pages → INP. Trust‑driven pages → CLS and INP. Long‑tail SEO → TTFB.


What the published case studies say

These are real, publicly reported results. Read them as existence proofs that the effect size can be large, not as forecasts for your site.

Organization Reported result Note
Vodafone 31% LCP improvement → +8% sales A/B tested against a control
Rakuten 24 Meeting CWV thresholds → +53% revenue per visitor, +33% conversion Compared periods, not a clean A/B
Farfetch Each 100 ms LCP improvement → +1.3% conversion Large luxury commerce catalog
redBus INP improvements → +7% sales Interaction‑led, not load‑led
Deloitte / Google ("Milliseconds Make Millions", 2020) 0.1 s mobile speed improvement → +8.4% retail conversions, +9.2% AOV Observational across many brands; the most‑quoted and most‑overstated figure in the industry

How to read these honestly:

  • Several are observational. Fast sessions and high‑converting sessions share confounders: better devices, better networks, richer users, returning customers with warm caches, and users who are further along in intent. Reverse causality is real too — a user who intends to buy loads more pages, warms more caches, and looks "faster".
  • The A/B‑tested ones (Vodafone) are the credible ones. Prefer them.
  • Effect sizes are highly non‑linear. Going 8 s → 5 s is worth far more than 2.5 s → 2.2 s. If you're already good, expect small numbers.

Never put "0.1 s = +8.4% conversion" in a business case as your forecast. If you apply it to Aurora Market's $1B, a 1‑second improvement "earns" $840M, which is more than the company's total margin. Any finance partner will notice, and your credibility is gone for the rest of the project.


Measuring your own elasticity

There are three methods, in ascending order of rigor.

Method A — Correlational bucketing (fast, weak, good enough to start)

Segment your own RUM by LCP bucket and compare conversion. You already have the data.

-- Sessions joined to orders, one row per session
SELECT
  CASE
    WHEN lcp_ms <  2000 THEN '0.0-2.0s'
    WHEN lcp_ms <  2500 THEN '2.0-2.5s'
    WHEN lcp_ms <  3000 THEN '2.5-3.0s'
    WHEN lcp_ms <  4000 THEN '3.0-4.0s'
    WHEN lcp_ms <  6000 THEN '4.0-6.0s'
    ELSE '6.0s+'
  END                                        AS lcp_bucket,
  COUNT(*)                                   AS sessions,
  AVG(converted::int)                        AS conversion_rate,
  AVG(revenue)                               AS revenue_per_session
FROM sessions
WHERE page_type = 'pdp'
  AND device_class = 'mobile'          -- hold device constant
  AND connection_type = '4g'           -- hold network constant
  AND is_returning = false             -- hold cache state constant
  AND date >= CURRENT_DATE - 28
GROUP BY 1 ORDER BY 1;

The WHERE clauses are the whole point. Without them you are measuring device quality, not speed. Even with them, this is correlation — present it as "sessions in the fastest bucket convert X% better", never as "if we get faster we will earn X".

Typical shape you'll see (illustrative, Aurora PDP, mobile, new visitors):

LCP bucket Sessions Conversion Rev/session
0.0–2.0 s 1.1M 3.9% $3.59
2.0–2.5 s 2.4M 3.4% $3.13
2.5–3.0 s 3.0M 2.9% $2.67
3.0–4.0 s 3.6M 2.3% $2.12
4.0–6.0 s 2.2M 1.6% $1.47
6.0 s+ 0.9M 0.9% $0.83

Note the curve steepens at the slow end. That's the normal shape, and it tells you to spend your effort on the p75–p95 tail, not on making the fast p25 faster.

Method B — A/B holdback (the honest one)

Ship the optimization behind a flag to 50% of traffic. This is the only method that establishes causation, and it is worth the extra week.

// app/product/[slug]/page.tsx — flag-gated rendering strategy
import { getFlag } from '@/lib/flags';

export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const fastPath = await getFlag('pdp-static-shell'); // 50/50, sticky per user

  return fastPath
    ? <ProductPageStaticShell slug={slug} />
    : <ProductPageLegacy slug={slug} />;
}

Rules that make the result trustworthy:

  • Sticky assignment per user, not per session, or returning users see both variants.
  • Run for at least two full business weeks — weekday/weekend and payday cycles matter in retail.
  • Pre‑register the primary metric (conversion rate) and the guardrails (revenue per session, AOV, error rate, add‑to‑cart rate). Deciding after you see the data is how teams fool themselves.
  • Verify the variant actually got faster in RUM, split by flag. Surprisingly often it didn't, and you would otherwise have concluded "speed doesn't matter here."
  • Expect to need large samples. Detecting a 1% relative lift on a 2.4% base conversion rate at 80% power needs roughly 1.5–2M sessions per arm. At Aurora's volume that's about two weeks; at 1M sessions/month it's not detectable and you should use Method A plus judgment.

Method C — Deliberate slowdown (the cleanest, and nobody does it)

Add 300 ms of artificial latency to 5% of traffic for a week. It's ethically fine at small scale (you're within normal variance for those users), it's causally clean, and it gives you the local slope of the curve at your current operating point.

Most orgs won't approve intentionally harming traffic. Ask anyway — sometimes the answer is yes, and one week of it settles a year of argument.


Writing the business case

A structure that survives scrutiny:

## Proposal: PDP rendering + image pipeline (6 engineer-weeks)

**Current state.** PDP p75 LCP is 4.6 s on mobile (target ≤2.5 s). 31% of sessions.
CDN HTML hit ratio 4% because the route is fully dynamic.

**Expected change.** p75 LCP 4.6 s → 2.2 s, based on a prototype measured in the lab
(trace attached) and confirmed on 1% canary traffic.

**Expected value — three scenarios:**
| Scenario | Assumed conversion lift | Annual GMV impact |
|---|---|---|
| Conservative | +0.5% relative | +$5.0M |
| Base | +1.5% relative | +$15.1M |
| Optimistic | +3.0% relative | +$30.2M |

Basis: our own LCP-bucket analysis shows sessions at 2.0–2.5 s convert 48% better than at
4.0–6.0 s; we discount that heavily because it is correlational. Vodafone's A/B-tested
31% LCP improvement produced +8% sales, which brackets our base case.

**How we'll know.** 50/50 flag holdback for 14 days. Primary: conversion rate.
Guardrails: revenue/session, AOV, JS error rate, add-to-cart rate. We will report the
measured lift, including if it is zero.

**Secondary benefits.** −$18K/mo CDN + origin compute (fewer dynamic renders);
faster crawl of the long-tail catalog.

**Risks.** Price/stock freshness on a cached shell — mitigated by streaming those from a
dynamic hole (design doc linked). Rollback is a flag flip.

Four things make this work: a range not a point estimate, an explicit statement that the correlational number is discounted, a pre‑committed measurement plan, and a rollback story. The line "we will report the measured lift, including if it is zero" buys more trust than any projection.


The costs nobody mentions

Be the person who raises these before someone else does:

  • Infrastructure savings are real and often ignored. Aurora's fully‑dynamic PDP costs ~$34K/mo in origin compute. A cacheable shell takes that to ~$9K/mo. That's a hard number finance likes more than a conversion forecast.
  • Performance work has a maintenance cost. Budgets, CI gates, and dashboards need an owner. Budget ~5% of a team's ongoing capacity or it decays within two quarters.
  • Some perf work makes DX worse (aggressive code splitting, RSC boundary discipline). Say so.
  • Regression is the default. Without gates, sites get ~10–20% slower per year through normal feature work. Half of any performance project's value is preventing the next regression.

Common mistakes

Mistake Why it hurts
Quoting the Deloitte 8.4% figure as a forecast Produces implausible numbers; destroys credibility
Comparing conversion of fast vs slow sessions with no controls Measures device wealth, not speed
Measuring only averages Perf distributions are right‑skewed; the tail is where the money is
Reporting Lighthouse score as the business metric Nobody buys more shoes because a score went 62 → 91
Shipping the fix and the measurement at the same time You can't attribute the result
Declaring victory on a lab number Field p75 is the truth; lab is a hypothesis generator

Lab 1.1 — Build your elasticity table

  1. Run the Method A query against your own data for your highest‑traffic page type. Hold device class, connection type, and returning‑visitor status constant.
  2. Plot conversion vs LCP bucket. Find where the curve steepens — that's your highest‑yield segment.
  3. Compute: if the sessions currently in your two slowest buckets moved one bucket faster, and they converted at that bucket's rate, what's the annual GMV delta? Label it clearly as an upper bound.
  4. Write a one‑page business case using the template above for one concrete change.
  5. Pre‑register the measurement plan before you write the code.

Checklist

  • Elasticity measured on your own data, with confounders controlled
  • Business case uses ranges, discounts correlational evidence, and names guardrail metrics
  • A/B holdback plan exists before implementation starts
  • Infrastructure cost savings included in the case
  • Ongoing maintenance capacity (~5%) explicitly requested

Next: 1.2 How pages actually load