All 26 checks with why-it-matters prose, severity, and cross-references to related audits.
ISO-25010 time-behaviour is measured by LCP — and Google's Core Web Vitals set the bar at 2.5 seconds. Miss it and you lose search ranking (LCP is a page experience signal), conversion rate (every 100ms of delay costs approximately 1% in revenue for e-commerce), and mobile users on slower connections who bounce before the page is usable. An unoptimized LCP element is typically the hero image or largest heading; when it loads without a preload directive or is lazy-loaded by mistake, the browser discovers it late in the waterfall, adding hundreds of milliseconds before the page looks complete.
Why this severity: Critical because a slow LCP directly degrades Core Web Vitals scores, suppresses search ranking, and correlates with measurable conversion loss at scale.
performance-core.loading-resource-priority.lcp-optimizedSee full patternISO-25010 time-behaviour starts the clock the moment a user's browser makes a request. TTFB above 800ms at the 75th percentile means a quarter of your users wait over a second before a single byte arrives — before any CSS, JavaScript, or content can render. Slow TTFB compounds every downstream metric: LCP, FCP, and INP all start later. For server-rendered applications without caching, every page hit cold-starts an origin server and may trigger database queries, turning user-perceived speed into a hostage of backend latency.
Why this severity: Critical because TTFB sets the floor for every subsequent performance metric; a slow origin delays LCP, FCP, and INP simultaneously with no mitigation possible on the client.
performance-core.loading-resource-priority.ttfb-targetSee full patternThe critical rendering path (ISO-25010 time-behaviour) is the chain of resources the browser must fetch and process before it can paint the first pixel. Each extra hop — a synchronous script in `<head>`, a monolithic render-blocking stylesheet, a sequential font request — adds a full network round-trip of latency. On mobile networks with 100–200ms RTT, three sequential blocking resources add 300–600ms of blank-screen time regardless of how fast your server is. This directly worsens FCP, LCP, and the user's first impression.
Why this severity: Critical because every render-blocking resource in the critical path is a mandatory delay before any visual content appears, compounding latency on every page load.
performance-core.loading-resource-priority.critical-pathSee full patternA render-blocking stylesheet halts all HTML parsing and painting until the browser has fully downloaded and parsed the CSS file (ISO-25010 time-behaviour). On a 3G connection, a 145 KB uncompressed stylesheet can block rendering for 800–1200ms on its own. Tailwind's JIT output, bundled third-party component libraries, and global reset files are common offenders — they pull in styles for elements that are not in the initial viewport, making the user wait for CSS they do not need until the page scrolls.
Why this severity: High because render-blocking CSS directly delays First Contentful Paint and LCP, and the penalty scales with file size and network conditions.
performance-core.loading-resource-priority.render-blocking-cssSee full patternBrowsers discover resources by parsing HTML top-to-bottom. Without preload directives, critical fonts are found only after the stylesheet is downloaded and parsed; the LCP image is found only after the CSS references it. That discovery gap — often 500–1000ms — is dead time during which the browser could have been fetching the resource (ISO-25010 time-behaviour). Missing a font preload causes invisible text (FOIT) or unstyled text (FOUT); missing an LCP image preload delays the most visible content on the page.
Why this severity: High because absent preload directives force late resource discovery, adding hundreds of milliseconds to LCP and font-render timing on every page load.
performance-core.loading-resource-priority.preload-criticalSee full patternEvery third-party origin requires a separate TCP connection and TLS handshake before the browser can send its first byte. On a typical network, that overhead is 100–300ms per origin (ISO-25010 time-behaviour). A page loading from fonts.googleapis.com, fonts.gstatic.com, and a CDN without preconnect directives pays that cost three times over — sequentially, if the browser has not yet opened those connections. The most visible symptom is delayed web font rendering, which blocks text display and contributes to layout shift.
Why this severity: Info because each missing preconnect adds 100–300ms of connection overhead per third-party origin, but the impact is bounded and depends on the number of distinct origins used.
performance-core.loading-resource-priority.preconnect-third-partySee full patternUntargeted prefetching wastes bandwidth — especially on mobile where users pay per megabyte. Unconditionally prefetching all `<Link>` hrefs in a Next.js app can download 2–3 MB of route bundles that the user never visits (ISO-25010 resource-utilisation). Conversely, missing prefetch on high-probability paths (a paginated list with a 90% chance the user clicks "next") adds 300ms of navigation delay on every click. The gap between what the user is likely to do and what the browser has prefetched is a measurable UX cost.
Why this severity: Low because the impact is a delay on predictable navigations or wasted bandwidth on low-probability prefetches — real but not blocking correct functionality.
performance-core.loading-resource-priority.resource-hintsSee full patternCumulative Layout Shift (CLS) above 0.1 means content visibly jumps while the user is reading or interacting — a failing Core Web Vitals score (ISO-25010 time-behaviour). The most common causes are images loading without declared dimensions (the browser reserves no space until the image arrives), late-injected ads that push content down, and font swaps that change line heights. A CLS above 0.25 causes accidental taps on the wrong element and is correlated with significantly higher bounce rates. Google uses CLS as a search ranking signal.
Why this severity: High because CLS above 0.1 is a failing Core Web Vitals score, degrades search ranking, and causes direct user errors from content jumping during interaction.
performance-core.rendering-paint.cls-fixedSee full patternInteraction to Next Paint (INP) replaced FID as a Core Web Vitals metric in 2024. INP above 200ms at the 75th percentile is a failing score that suppresses Google search ranking (ISO-25010 time-behaviour). The root cause is always the same: JavaScript running synchronously on the main thread — form submit handlers doing JSON parsing, click handlers firing analytics events, data table sorts blocking the UI. Every millisecond the main thread is busy is a millisecond the browser cannot render the response to the user's action, making the app feel broken.
Why this severity: High because INP above 200ms is a failing Core Web Vitals score, signals unresponsive UI to users, and directly hurts search ranking as of 2024.
performance-core.rendering-paint.inp-fid-targetSee full patternAny JavaScript task running for more than 50ms continuously blocks the browser's main thread (ISO-25010 time-behaviour). During that time the browser cannot respond to user input, run animations, or update the UI. The result is a UI that feels frozen or laggy — users experience input lag even if no interaction is happening, because the browser is busy with work they did not trigger. Long tasks are the most common root cause of poor INP and Total Blocking Time scores, and they compound when multiple libraries initialize sequentially at page load.
Why this severity: High because tasks over 50ms directly block the main thread, preventing the browser from responding to user input and degrading INP — a Core Web Vitals ranking signal.
performance-core.rendering-paint.long-tasksSee full pattern`will-change` promotes an element to its own GPU compositing layer (ISO-25010 resource-utilisation). Used correctly on a single animating modal, that is a genuine win. Applied globally in CSS to 20+ static elements — headers, footers, card wrappers that never move — it creates 20+ permanent GPU layers, consuming VRAM on every device. On mobile with limited VRAM, this causes compositor memory pressure, degrades scroll performance, and can make the browser drop frames on animations it would otherwise handle smoothly. Misuse is the opposite of its intended effect.
Why this severity: Low because overuse of `will-change` degrades GPU memory and scroll performance rather than breaking functionality, but the degradation is measurable and worsens on low-end devices.
performance-core.rendering-paint.will-changeSee full patternEager-loading all images transfers bytes the user may never scroll to see (ISO-25010 time-behaviour). A product listing page with eight gallery images below the fold can waste 450 KB on initial load — bytes that delay the LCP image, consume mobile data allowances, and increase time-to-interactive on slow connections. The browser's native `loading="lazy"` attribute costs one attribute; the performance payoff is the elimination of all below-fold image requests until the images actually enter the viewport.
Why this severity: Medium because loading below-fold images eagerly wastes bandwidth and delays initial render, with measurable impact on mobile users and slow connections.
performance-core.image-media-optimization.lazy-loadingSee full patternWebP provides 25–34% smaller file sizes than JPEG at equivalent visual quality; AVIF provides 50% smaller sizes. Serving legacy JPEG or PNG to browsers that support modern formats wastes bandwidth on every image request (ISO-25010 resource-utilisation). A page with ten product images at 200 KB each becomes a page with ten images at 130 KB each in WebP — a 700 KB savings per page load that directly reduces LCP, speeds up the gallery render, and cuts mobile data costs for users.
Why this severity: Medium because serving only JPEG/PNG wastes 25–50% of image transfer bytes on modern browsers that support WebP or AVIF, with compounding impact on image-heavy pages.
performance-core.image-media-optimization.next-gen-formatsSee full patternA 2400-pixel-wide hero image served to a 375-pixel mobile viewport transfers 1.2 MB to display roughly 110 KB of visual information (ISO-25010 resource-utilisation). Without `srcset` and `sizes`, the browser has no signal to choose a smaller variant — it downloads the full-resolution image regardless of device. Multiply that across ten images on a product page and mobile users are downloading 10x the pixels they can display, with proportional impact on page weight, LCP, and data cost.
Why this severity: Medium because absent `srcset`/`sizes` causes mobile devices to download full-resolution images they cannot fully display, wasting significant bandwidth on every visit.
performance-core.image-media-optimization.responsive-imagesSee full patternWithout `font-display`, the browser's default behavior is to block text rendering for up to 3 seconds while waiting for the web font to download — Flash of Invisible Text (FOIT). On slow connections, users see blank text boxes where your content should be (ISO-25010 time-behaviour). Even on fast connections, FOIT contributes to CLS when the font finally loads and changes character widths, causing visible layout shift. Every web font without `font-display: swap` is a potential 3-second invisible-text window.
Why this severity: Medium because missing `font-display` causes up to 3 seconds of invisible text on slow connections and triggers CLS-contributing font swaps when the web font finally loads.
performance-core.image-media-optimization.font-displaySee full patternA `<video>` element without a `poster` attribute renders a blank or black rectangle until the user interacts with it (ISO-25010 time-behaviour). On autoplay-restricted mobile browsers, a video without a poster remains visually empty indefinitely. This degrades perceived page quality, makes above-fold video sections look broken on slow connections, and signals to users that the page has not fully loaded. A properly optimized poster image adds negligible bytes while providing immediate visual feedback.
Why this severity: Low because missing poster images degrade perceived page completeness and visual polish but do not break core functionality or expose security risks.
performance-core.image-media-optimization.video-posterSee full patternSynchronous third-party scripts in `<head>` block HTML parsing from the moment the browser encounters them (ISO-25010 time-behaviour). A page with four analytics and marketing scripts loading synchronously — Google Analytics, Segment, Drift, Intercom — commonly adds 200–400ms of render-blocking time before any content displays. That delay is entirely external to your codebase: network latency, third-party CDN performance, and script execution time are all out of your control, yet they block your page from rendering.
Why this severity: High because synchronous third-party scripts block the entire HTML parsing pipeline, adding uncontrolled latency from external CDNs before any first-party content can render.
performance-core.script-style-efficiency.third-party-asyncSee full patternWithout CSS containment, updating one component in a data table, carousel, or real-time dashboard causes the browser to recalculate layout and repaint for the entire document — not just the changed element (ISO-25010 resource-utilisation). On a dashboard with 12 widgets where one widget polls every second, that means 12 full-page layout passes per second. `contain: layout paint` tells the browser the component is visually isolated, scoping style and layout work to the component boundary and dramatically reducing render overhead for complex UIs.
Why this severity: Medium because missing CSS containment on complex components causes unnecessary document-wide layout recalculation on every update, degrading animation frame rate and scroll performance.
performance-core.script-style-efficiency.css-containmentSee full patternJavaScript has a single main thread. A synchronous CSV export that filters and serializes 50,000 rows, or a bcrypt hash in a form submit handler, blocks the main thread for 200–400ms (ISO-25010 time-behaviour). During that time the browser cannot respond to any user input, animate CSS transitions, or process other JavaScript. The UI appears frozen. Web Workers solve this by running the computation on a separate thread, leaving the main thread free to handle interactions — but only if the developer moves the work there deliberately.
Why this severity: Low because CPU-heavy main-thread operations freeze the UI only during the computation, not continuously — but the freeze is user-visible and reproducible on every trigger.
performance-core.script-style-efficiency.web-workerSee full patternInterleaving DOM reads and writes in a loop forces the browser to recalculate layout after every write before it can serve the next read — called "layout thrashing" (ISO-25010 time-behaviour). Reading `element.offsetHeight` after setting `element.style.height` on 100 elements triggers 100 synchronous layout recalculations instead of one. On a 60Hz display, each recalculation costs approximately 16ms of budget. One thrashing loop can consume the entire frame budget, causing the browser to drop frames and producing visible jank.
Why this severity: Low because layout thrashing causes visible jank and dropped frames during the specific interaction that triggers it, but does not affect baseline performance outside those code paths.
performance-core.script-style-efficiency.layout-thrashingSee full patternWithout a Service Worker caching strategy, every visit to your site requires a full round-trip to the origin for every asset (ISO-25010 time-behaviour). On return visits — where a Service Worker could serve assets from cache in under 1ms — users experience full network latency instead. A missing cache versioning strategy means that when you deploy, old Service Worker caches persist and serve stale JavaScript, CSS, or HTML until the user manually clears their cache. Stale Service Worker caches are one of the hardest classes of production bug to diagnose.
Why this severity: Low because Service Worker absence degrades return-visit performance and offline resilience but does not break initial functionality on the live network.
performance-core.script-style-efficiency.service-workerSee full patternHTTP/1.1 limits browsers to 6 parallel TCP connections per origin. A page loading 30 assets — JS chunks, CSS, images, fonts — from a single origin serializes those requests into 5 batches, each waiting for the previous to finish (ISO-25010 time-behaviour). HTTP/2 multiplexes all requests over a single connection with no per-connection limit, eliminating the batching delay entirely. HTTP/3 adds QUIC transport, removing the head-of-line blocking that HTTP/2 still has at the TCP layer. Remaining on HTTP/1.1 in 2025 is a structural performance penalty.
Why this severity: Low because HTTP/1.1 adds measurable latency on asset-heavy pages but most modern hosting platforms default to HTTP/2, so the finding typically reflects a misconfiguration rather than a missing feature.
performance-core.script-style-efficiency.http2-enabledSee full patternUncompressed text assets transfer 2–5x more bytes than their compressed equivalents (ISO-25010 resource-utilisation). A 245 KB JavaScript bundle served without compression transfers 245 KB; with Brotli compression it transfers approximately 55 KB — a 78% reduction. Every kilobyte saved reduces time-to-interactive on constrained connections, cuts CDN egress costs, and directly improves LCP for users on slower networks. Brotli consistently outperforms gzip by 15–25%, making it the preferred algorithm for static text assets.
Why this severity: Low because major hosting platforms enable compression by default, so this finding usually indicates a custom server misconfiguration rather than a novel issue — but the byte impact can be substantial.
performance-core.script-style-efficiency.compressionSee full patternAn origin server in us-east-1 adds 150–300ms of network latency for users in APAC or Europe before a single byte of content arrives (ISO-25010 time-behaviour). A CDN with geographic edge caching eliminates that latency by serving cached responses from the PoP nearest the user. Separately, static assets served without `Cache-Control: immutable, max-age=31536000` are re-validated on every visit, incurring a conditional request round-trip even when the asset has not changed. Both issues compound on high-traffic pages.
Why this severity: Info because CDN and cache-control gaps are genuinely harmful at scale but commonly resolved automatically by modern hosting platforms, making the finding most relevant to custom or self-hosted deployments.
performance-core.script-style-efficiency.cdn-cachingSee full patternWithout profiling, decisions about how to load third-party scripts are guesses (ISO-25010 time-behaviour). A chat widget assumed to be lightweight may consume 120ms of main thread time on load; an analytics script deferred as low-priority may block a critical interaction. Without measured execution times per script, you cannot prioritize optimization work or justify removing a vendor. Unknown third-party impact is one of the most common causes of unexplained performance regressions when a new marketing tag is added.
Why this severity: Info because unprofiled third-party scripts represent unknown latency risk rather than a confirmed performance problem — the impact could be negligible or severe, which is exactly the issue.
performance-core.script-style-efficiency.third-party-profileSee full patternWithout a performance budget enforced in CI, bundle size, LCP, and CLS regressions go undetected until users report slowness (ISO-25010 capacity). A JavaScript bundle that grew from 150 KB to 500 KB over six months — one dependency upgrade at a time — produces no build error and no alert. Performance budgets create an automated gate: the build fails when the bundle exceeds the limit, turning performance regression into a first-class CI failure alongside type errors and test failures. Without this gate, performance optimization is reactive rather than preventive.
Why this severity: Info because missing performance budgets allow regressions to ship silently over time, but the immediate impact is potential rather than confirmed — a process gap rather than a current defect.
performance-core.script-style-efficiency.performance-budgetSee full patternRun this audit in your AI coding tool (Claude Code, Cursor, Bolt, etc.) and submit results here for scoring and benchmarks.
Open Performance Core Audit