← Graph

How I brought LCP down to under 350 ms

talk 18 connections

Paweł Pokrywka's wroclove.rb 2024 talk explaining how he brought Largest Contentful Paint on planujewesele.pl below 350 ms (real number even lower; rounded up to avoid disbelief). Covers: why LCP matters (Google SEO ranking boost below 2.5 s, conversion-rate impact), a live demo of a cached Google search result loading in ~140 ms on throttled 3G, reverse-engineering the HTML to reveal that Google does NOT use naive `<link rel=prefetch>` (privacy leakage of user IPs via referer, lack of control over prefetched bytes), history of AMP (2015, simplified HTML framework, mobile-only, ugly google.com URLs, trust issues), the 2018 invention of Signed Exchanges (sxg) as a draft standard supported by Chromium browsers, Cloudflare, an nginx module, and Fastly. Walks through how SXG works end-to-end (Googlebot requests with Accept: signed-exchange, server returns a signed package, Google stores it in the opaque SXG cache, browser prefetches from web-pkg-c.com, and decoded SXG is served on click). Basic implementation: one-click toggle in a $20/month Cloudflare subscription. Full implementation requires decoupling request from response: Cache-Control: public with max-age between 120s and 7 days (speaker uses 24 h; Googlebot keeps it fresh), no server-side personalization, no server-side cookies (session cookie moved to a dedicated endpoint, avatar/username to client-side, CSRF moved client-side, HSTS header removed). 'First impression optimization' assumes anonymous visitor to avoid hitting auth endpoints — useful for crawler budget. Sub-resource prefetching uses the Link HTTP header with SHA hashes per URL; Cloudflare's Automatic Signed Exchanges (ASX) generates these, but Rails' built-in Link header for early hints takes precedence and had to be stripped for SXG responses via a Cloudflare Worker. Sub-resources have strict rules: Cache-Control (1 year ideal), no cookies, no HSTS, must share the main domain (a Cloudflare Worker rewrites CDN URLs), max ~20 resources, all-or-nothing prefetching (one failure discards all — for privacy). CORS-looking errors usually mask cache misses in the underdocumented Google SXG cache; Cloudflare even returns different responses to Googlebot vs curl. Debugging tools: Chrome DevTools (enable/disable cache carefully), an SXG prefetch simulator page, the SXG Validator browser extension (unstable, false negatives), curl (but disable Cloudflare Bot Fight Mode first), the Requestly browser header-modifying extension, Google Search Console's URL inspection. Measurement: naive before/after is swamped by seasonal bias and low signal-to-noise; Cloudflare injects a `window.isSXG` flag but SXG traffic is biased (users saw the site high in SERPs). Best approach: compare SXG-with-working-sub-resources to SXG-with-broken-prefetch using a Canary sub-resource detected via JavaScript (a future 'poisonous' sub-resource will always fail for A/B). Q&A: does SXG break on its own due to Google changes? Speaker only started tracking error rate while preparing this talk, so doesn't yet know.

type
talk
talk How I brought LCP down to under 350 ms
about
Entire talk is about bringing LCP below 350 ms.
talk How I brought LCP down to under 350 ms
about
SXG is the core technology used to reduce LCP.
talk How I brought LCP down to under 350 ms
about
Talk traces the history from AMP (2015) to SXG (2018).
talk How I brought LCP down to under 350 ms
about
Covers sub-resource prefetching as the phase yielding the biggest LCP wins.
talk How I brought LCP down to under 350 ms
about
Core Web Vitals concept
Frames LCP as one of the Core Web Vitals used by Google ranking.
talk How I brought LCP down to under 350 ms
about
Cloudflare's ASX is the concrete implementation used.
talk How I brought LCP down to under 350 ms
about
Used to strip Rails Link header and rewrite CDN URLs for SXG.
talk How I brought LCP down to under 350 ms
about
Core opaque component at the heart of SXG's behavior and debugging problems.
talk How I brought LCP down to under 350 ms
about
Crawler Budget concept
Motivates 'first impression optimization' to save requests for crawlers.
talk How I brought LCP down to under 350 ms
about
Describes the canary approach for detecting successful prefetching.
talk How I brought LCP down to under 350 ms
about
Talk starts from naive <link rel=prefetch> before introducing SXG.
asked_at
How I brought LCP down to under 350 ms talk
Audience Q&A after the wroclove.rb 2024 talk.
authored
How I brought LCP down to under 350 ms talk
Speaker of the wroclove.rb 2024 talk on SXG-based LCP optimization.
from_talk
How I brought LCP down to under 350 ms talk
Core design insight distilled from the talk's SXG/AMP comparison.
from_talk
How I brought LCP down to under 350 ms talk
Mental-model recommendation for adopting SXG successfully.
from_talk
How I brought LCP down to under 350 ms talk
Measurement methodology recommended in the talk.
from_talk
How I brought LCP down to under 350 ms talk
Debugging tip for multi-layer (Cloudflare/Google/browser) caches.
talk How I brought LCP down to under 350 ms
presented_at
Delivered at wroclove.rb 2024.

Provenance

Created
2026-04-17 16:17 seed
Read by
14 extractions