Ensure your application truly works in real-world low-resource environments by validating performance, usability, resilience, and efficiency against defined benchmarks.
Overview
Measurement and testing ensure that applications truly work in real-world low-resource environments by validating performance, usability, resilience, and efficiency against defined benchmarks.
Key idea in an LRO context: The key principle is "test in real constraints, not ideal conditions." Success is defined not by lab performance on fast devices but by consistent usability on slow networks, low-end devices, and constrained environments.
Why this matters for low-resource users
User impact
- Slow networks amplify performance issues significantly.
- Low-end devices magnify CPU, memory, and rendering inefficiencies.
- Expensive data plans make inefficient pages costly to users.
- Unstable connectivity exposes resilience gaps.
Risks if ignored
- Sites pass internal QA but fail real users.
- Poor performance leads to abandonment and mistrust.
- Hidden inefficiencies increase data and battery usage.
- Accessibility and usability gaps remain undetected.
Common problems
Typical issues seen
- Testing only on high-speed Wi-Fi and modern devices.
- Ignoring real-user metrics and relying only on lab scores.
- No performance budgets or thresholds defined.
- Missing testing for offline or flaky networks.
- Overlooking low-end Android device performance.
- Measuring only performance but not UX.
Why they fail in LRO contexts
- Real-world constraints are much harsher than lab environments.
- Network latency and packet loss expose hidden inefficiencies.
- Low CPU and RAM amplify JavaScript and rendering costs.
- Lack of holistic measurement ignores usability and resilience.
Benchmarking
Below is a comprehensive set of key website performance metrics organised by category. Select a tab to explore each metric set.
The tables under the tabs below cover key website performance metrics. Each metric contributes based on its weighting. Weighted scores add up to the overall performance score: 0–300.
Traffic light legend
- 🟢 Green — Excellent / Optimal Experience (270–300): Users perceive the site as fast, stable, and delightful. Maintain and monitor for regressions.
- 🟡 Amber — Acceptable / Needs Optimisation (150–269): Usable but friction is visible; users may notice lag or instability. Identify bottlenecks and prioritise fixes.
- 🔴 Red — Poor / At-Risk Experience (0–149): Users experience frustration — long waits, layout jumps, slow inputs. Immediate action required.
| Metric | What it measures | Weighting | Score Bands | UX Relevance |
|---|---|---|---|---|
| Loading & Rendering | ||||
| Largest Contentful Paint (LCP) | The largest visible element (hero image, heading, etc.) renders within 2.5s. Reflects how quickly users see what they came for. | 20 | 🟢 ≤2.5s 🟡 2.5–4s 🔴 >4s |
Fast-loading content keeps visitors engaged and helps them access information without delay. |
| First Contentful Paint (FCP) | When the first visual element (text/image) appears — provides immediate feedback that the page is loading. | 10 | 🟢 ≤1.8s 🟡 1.9–3s 🔴 >3s |
Provides immediate visual feedback that the page is loading, creating a positive first impression. |
| Time to First Byte (TTFB) | Time for the browser to receive the first byte from the server. Indicates backend or CDN efficiency. | 8 | 🟢 ≤500ms 🟡 500–1000ms 🔴 >1s |
Sets the foundation for all other performance metrics; a responsive server creates a smooth experience. |
| Total Blocking Time (TBT) | How long the page is unresponsive during loading. | 12 | 🟢 ≤200ms 🟡 200–600ms 🔴 >600ms |
Ensures visitors can interact smoothly with buttons, links, and forms from the moment they appear. |
| Speed Index | Measures how quickly visible content is displayed during loading — a smoothness indicator. | 8 | 🟢 ≤3s 🟡 3–5s 🔴 >5s |
Progressive, smooth loading creates a perception of speed that keeps users engaged and informed. |
| Interaction to Next Paint (INP) | Time between user interaction (click/tap) and visible response. Shows how responsive the interface feels. | 7 | 🟢 ≤200ms 🟡 201–500ms 🔴 >500ms |
Instant feedback to clicks and taps builds confidence and makes the site feel professional and polished. |
| First CPU Idle | When the page is ready for basic interactions. | 5 | 🟢 ≤3.5s 🟡 3.6–5s 🔴 >5s |
Allows visitors to begin their tasks quickly and efficiently. |
| Code & Assets | ||||
| JavaScript Bundle Size | Total size of JavaScript files loaded. | 10 | 🟢 ≤150KB 🟡 151–300KB 🔴 >300KB |
Leaner code means faster processing and smoother interactions, particularly on mobile devices. |
| Critical JS | Size of JavaScript needed for initial render. | 6 | 🟢 ≤30KB 🟡 31–60KB 🔴 >60KB |
Minimising essential scripts gets visitors to meaningful content faster. |
| CSS Bundle Size | Total size of style sheets loaded. | 8 | 🟢 ≤50KB 🟡 51–100KB 🔴 >100KB |
Streamlined styling ensures the design appears quickly and consistently. |
| Critical CSS Inline | Amount of CSS embedded in the HTML. | 5 | 🟢 ≤15KB 🟡 16–30KB 🔴 >30KB |
The right balance ensures fast initial rendering while maintaining optimal performance. |
| Total Page Weight | Combined size of all initial resources. | 15 | 🟢 ≤500KB 🟡 501KB–1MB 🔴 >1MB |
Lighter pages work beautifully on varied network conditions and help users conserve mobile data. |
| HTTP Requests | Number of separate resource requests made. | 5 | 🟢 ≤50 🟡 51–100 🔴 >100 |
Fewer requests mean faster loading through improved network efficiency. |
| Third-Party Scripts | External code from analytics, ads, etc. | 6 | 🟢 ≤3 scripts / 50KB 🟡 moderate 🔴 excessive |
Controlled third-party code maintains the performance standards visitors expect. |
| Images & Media | ||||
| Image Size | File size of individual images. | 12 | 🟢 ≤100KB 🟡 101–250KB 🔴 >250KB |
Optimised images deliver visual impact without compromising speed — one of the most effective improvements. |
| Above-the-Fold Images | Number of images visible on initial load. | 5 | 🟢 ≤3 images 🟡 4–6 🔴 >6 |
Focusing on essential visuals ensures visitors see meaningful content immediately. |
| Preferred Formats | Use of modern image formats (WebP/AVIF). | 5 | 🟢 100% 🟡 partial 🔴 none |
Next-generation formats deliver high-quality visuals at 20–30% smaller file sizes. |
| Lazy Loading | Images load only when needed. | 7 | 🟢 all 🟡 partial 🔴 none |
Smart loading prioritises visible content while conserving bandwidth and device resources. |
| Video Usage | Video file sizes and autoplay settings. | 6 | 🟢 ≤1MB preview 🟡 moderate 🔴 heavy |
Thoughtful video implementation works effectively across all devices and connection speeds. |
| SVGs | Use and optimisation of vector graphics. | 3 | 🟢 ≤5KB 🟡 larger 🔴 too heavy |
Lightweight vectors scale perfectly on any screen while loading near-instantly. |
| Fonts | ||||
| Font Size | Total file size of web fonts. | 6 | 🟢 ≤50KB 🟡 51–100KB 🔴 >100KB |
Optimised fonts ensure beautiful typography renders quickly and consistently. |
| Max Families | Number of different font families used. | 4 | 🟢 ≤2 🟡 3–4 🔴 >4 |
Focused typography choices create visual consistency while maintaining fast load times. |
| Preload Critical Fonts | Priority loading for essential fonts. | 3 | 🟢 yes 🟡 partial 🔴 no |
Ensures headlines and key text appear instantly without jarring layout shifts. |
| Fallbacks Defined | System font alternatives specified. | 3 | 🟢 yes 🟡 partial 🔴 no |
Guarantees readable text at all times, even during slower font loading. |
| Resilience & Usability | ||||
| Keyboard Navigation | Full support for keyboard-only users. | 5 | 🟢 full 🟡 partial 🔴 none |
Welcomes the 15–20% of visitors who rely on keyboards or assistive technologies. |
| Text-first Mode | Core content accessible without enhancements. | 6 | 🟢 yes 🟡 partial 🔴 no |
Ensures the message reaches visitors even when images or scripts encounter loading issues. |
| Offline First | Key assets cached for offline use. | 5 | 🟢 yes 🟡 partial 🔴 no |
Provides a reliable experience even when network connections are unstable or intermittent. |
| Graceful Degradation | Functionality on older/budget devices. | 5 | 🟢 yes 🟡 partial 🔴 no |
Extends reach to visitors worldwide, regardless of their device capabilities. |
| Progressive Enhancement | Core features work without JavaScript. | 5 | 🟢 yes 🟡 partial 🔴 no |
Ensures universal access by making core functionality available to everyone. |
| Network Efficiency | ||||
| Critical Rendering Path | Number/size of resources blocking initial render. | 7 | 🟢 ≤75KB 🟡 76–150KB 🔴 >150KB |
Streamlined critical resources enable faster time to interactive and visible content. |
| Caching – HTML | Short caching for HTML. | 3 | 🟢 ≤5 min TTL 🟡 longer 🔴 none |
— |
| Caching – Assets | Cache assets for long periods. | 5 | 🟢 ≥30 days 🟡 partial 🔴 none |
— |
| Compression | Gzip/Brotli enabled for text assets. | 5 | 🟢 all 🟡 partial 🔴 none |
60–80% file size reduction delivers faster experiences without compromising content quality. |
| Protocols | Modern protocol (HTTP/2+) for parallel requests. | 5 | 🟢 yes 🟡 partial 🔴 no |
Enables parallel requests and faster resource delivery — a standard for modern web experiences. |
| CDN Usage | Content delivery network implementation. | 7 | 🟢 yes 🟡 partial 🔴 no |
Reduces latency by serving content from geographically closer servers, benefiting global audiences. |
| Testing Environments | ||||
| Network Simulation | Test on slow 3G. | 5 | 🟢 tested 🟡 partial 🔴 not tested |
Testing on slower networks ensures your site remains accessible for visitors in areas with limited connectivity. |
| Device Testing | Test on low-end devices. | 5 | 🟢 tested 🟡 partial 🔴 not tested |
Validating on budget devices guarantees all visitors enjoy a smooth experience regardless of hardware. |
| Battery Usage | Efficient use of mobile battery. | 3 | 🟢 ≤2% / 5 min 🟡 moderate 🔴 heavy |
Efficient battery consumption shows respect for visitors' device resources, allowing them to browse longer. |
| Total Score | ~300 points | |||
For technical details on these metrics and how to achieve the benchmarks, see the Developer supplement tab.
Measuring and improving user experience (UX) can be challenging — optimising it isn't just about design, but about performance, ease of use, and how well a site meets user expectations.
- UX measurement should be context-driven, rather than method-driven.
- Balanced evaluation combines quantitative data (what users do) with qualitative insights (why they do it).
| Metric | What it measures | Score Bands | Impact on user experience |
|---|---|---|---|
| Content Engagement | |||
| Scroll Depth | Percentage of page scrolled by users. | 🟢 ≥75% 🟡 50–74% 🔴 <50% |
Deep scrolling signals compelling content that maintains user interest and encourages thorough exploration. |
| Time on Page | Average duration users spend on page. | 🟢 ≥2 min 🟡 1–2 min 🔴 <1 min |
Longer engagement time indicates valuable, relevant content that meets user needs and expectations. |
| Bounce Rate | Percentage of single-page sessions. | 🟢 <40% 🟡 40–60% 🔴 >60% |
Lower bounce rates suggest users find what they're looking for and are motivated to explore further. |
| Navigation & Findability | |||
| Navigation Clarity | Ease of finding key content and features. | 🟢 excellent 🟡 good 🔴 poor |
Intuitive navigation reduces cognitive load and helps users accomplish their goals efficiently. |
| Search Effectiveness | Success rate of on-site search. | 🟢 ≥80% 🟡 60–79% 🔴 <60% |
Effective search helps users quickly locate specific information, minimising frustration and reducing site abandonment. |
| Click Depth | Number of clicks to reach key content. | 🟢 ≤3 🟡 4–5 🔴 >5 |
Shorter paths to content reduce user effort and improve task completion rates. |
| Accessibility | |||
| Accessibility Score | WCAG/Lighthouse compliance rating. | 🟢 ≥90 🟡 70–89 🔴 <70 |
High accessibility ensures all users, regardless of ability, can navigate and interact with confidence. |
| Screen Reader Compatibility | Support for assistive technologies. | 🟢 full 🟡 partial 🔴 limited |
Proper screen reader support enables visually impaired users to access all content and functionality. |
| Animations | No heavy or autoplay animations. | 🟢 light 🟡 moderate 🔴 heavy |
Optimised animations provide visual delight without causing performance issues or user discomfort. |
| Reduced Motion Support | Respects user motion preferences. | 🟢 full 🟡 partial 🔴 none |
Respecting motion preferences prevents disorientation and discomfort for motion-sensitive users. |
| Color Contrast | Text easily readable. | 🟢 WCAG AA 🟡 partial 🔴 poor |
Sufficient contrast ensures all text is readable, reducing eye strain and improving comprehension. |
| Tap Targets | Minimum size and spacing for touch — buttons/links large enough. | 🟢 ≥48px 🟡 slightly smaller 🔴 too small |
Adequate touch targets prevent mis-taps and enable confident, accurate interactions on mobile devices. |
| Form Label Association | Proper labelling of form inputs. | 🟢 100% 🟡 partial 🔴 missing |
Clear form labels help all users understand input requirements and reduce completion errors. |
| Visual Stability | |||
| Layout Stability (CLS) | No shifting content. Measures how much content shifts unexpectedly as it loads. Lower values mean smoother, more predictable interfaces. | 🟢 ≤0.05 🟡 0.06–0.1 🔴 >0.1 |
Prevents accidental clicks, improves perceived quality. |
| Responsiveness | |||
| Mobile Usability | Effectiveness on mobile devices. | 🟢 excellent 🟡 good 🔴 poor |
Mobile-optimised design ensures smooth experiences for the majority of users accessing via smartphones. |
| Touch vs Click Optimisation | Interface adaptation for input method. | 🟢 adaptive 🟡 partial 🔴 none |
Input-optimised interfaces feel natural whether users navigate with touch, mouse, or keyboard. |
| Interactivity | |||
| Interaction to Next Paint (INP) | Overall interaction responsiveness. | 🟢 ≤200ms 🟡 201–500ms 🔴 >500ms |
Quick visual feedback to all interactions creates a fluid, responsive experience that feels alive. |
| Button and Link States | Visual feedback for interactive elements. | 🟢 all states 🟡 partial 🔴 missing |
Clear hover, focus, and active states provide reassurance that interactions have been registered. |
| Readability | |||
| Font Size | Base text size for body content. | 🟢 ≥16px 🟡 14–15px 🔴 <14px |
Adequate font size reduces eye strain and makes content accessible without zooming. |
| Line Height | Spacing between lines of text. | 🟢 1.5–1.8 🟡 1.3–1.4 🔴 <1.3 |
Comfortable line spacing improves reading flow and comprehension, especially for longer content. |
| Line Length | Characters per line of text. | 🟢 50–75 ch 🟡 40–49 / 76–90 🔴 outside range |
Optimal line length prevents eye fatigue and maintains reading rhythm for better comprehension. |
| Content Hierarchy | Clear visual distinction of headings/sections. | 🟢 clear 🟡 moderate 🔴 weak |
Strong hierarchy helps users quickly scan and locate relevant information within the content. |
| Error Handling | |||
| Error Messages | Clarity and helpfulness of error feedback. | 🟢 clear / helpful 🟡 adequate 🔴 unclear |
Helpful error messages guide users to a resolution rather than leaving them frustrated and confused. |
| Form Validation | Real-time feedback on form inputs. | 🟢 inline 🟡 on-submit 🔴 none |
Immediate validation helps users correct errors quickly, reducing friction in form completion. |
These additional metrics extend the core LRO performance framework to better reflect the real-world conditions of low-resource users, such as limited bandwidth, low-end devices, unstable connectivity, and high data costs. They focus on areas not fully captured by standard web performance metrics, including data efficiency, resilience, device constraints, interaction simplicity, and perceived performance.
Developers should first target and validate the core performance metrics (page weight, load time, critical rendering performance) before working on these additional metrics. Once baseline targets are met, these metrics can drive deeper improvements in usability, reliability, and inclusivity for low-resource environments.
| Metric | Description | Benchmark | Thresholds | Tools |
|---|---|---|---|---|
| Data Efficiency | ||||
| Data Cost per Page Load | Total MB downloaded on first load. | ≤ 0.3 MB | 🟢 ≤0.3 MB 🟡 0.3–0.7 MB 🔴 >0.7 MB |
Chrome DevTools, WebPageTest |
| Repeat Visit Data Usage | Bytes downloaded on second visit (cache effectiveness). | ≤ 50 KB | 🟢 ≤50 KB 🟡 50–150 KB 🔴 >150 KB |
Lighthouse, DevTools |
| Image Bytes Ratio | % of total payload from images. | ≤ 30% | 🟢 ≤30% 🟡 31–50% 🔴 >50% |
WebPageTest |
| Resilience & Reliability | ||||
| Partial Load Usability | % of core content visible if JS fails. | ≥ 80% | 🟢 ≥80% 🟡 50–79% 🔴 <50% |
Disable JS test, manual audit |
| Retry Friendliness | Failed requests auto-retry gracefully. | Enabled | 🟢 Yes 🟡 Partial 🔴 No |
Network logs |
| Device Constraints | ||||
| Peak Memory Usage | Max RAM used during load. | ≤ 150 MB | 🟢 ≤150 MB 🟡 150–300 MB 🔴 >300 MB |
Chrome Performance Profiler |
| JS Execution Time | Time spent parsing & running JS. | ≤ 1.5s | 🟢 ≤1.5s 🟡 1.5–3s 🔴 >3s |
Lighthouse, DevTools |
| DOM Node Count | Total DOM elements rendered. | ≤ 800 | 🟢 ≤800 🟡 800–1500 🔴 >1500 |
DevTools Elements |
| Energy & Battery | ||||
| CPU Wakeups per Minute | Background JS activity. | ≤ 5 / min | 🟢 ≤5 🟡 6–15 🔴 >15 |
Chrome Performance tab |
| Network Requests After Idle | Requests fired after page load completes. | None | 🟢 None 🟡 Minimal 🔴 Frequent |
DevTools Network |
| Compatibility | ||||
| Old Browser Support | Works on older Android/Chrome versions. | Full | 🟢 Full 🟡 Partial 🔴 Broken |
BrowserStack |
| No-JS Mode Coverage | Content visible without JS. | ≥ 80% | 🟢 ≥80% 🟡 50–79% 🔴 <50% |
Disable JS test |
| Perceived Performance | ||||
| Time to First Meaningful Text | Time until readable content appears. | ≤ 1s | 🟢 ≤1s 🟡 1–3s 🔴 >3s |
Lighthouse |
| Blank Screen Time | White screen duration. | ≤ 0.5s | 🟢 ≤0.5s 🟡 0.5–2s 🔴 >2s |
WebPageTest |
| User Control & Transparency | ||||
| Low-Data Mode Toggle | User can enable lite mode. | Available | 🟢 Yes 🟡 Hidden 🔴 No |
Product review |
| Data Usage Disclosure | Warns user before heavy download. | Always | 🟢 Always 🟡 Sometimes 🔴 Never |
UX review |
See the Developer supplement tab for technical guidance on how to measure each of these additional metrics.
Use the standardised profiles below for consistent LRO testing across browsers and environments.
Network conditions
| Profile | Download | Upload | Latency |
|---|---|---|---|
| 2G (Low-end Rural) | 250 kbps | 50 kbps | 400 ms |
| Slow 3G (Emerging Market) | 700 kbps | 250 kbps | 300 ms |
| Fast 3G (Urban Developing) | 1,600 kbps | 750 kbps | 150 ms |
| Low 4G (Budget Phone) | 4,000 kbps | 1,500 kbps | 100 ms |
| Public Wi-Fi (Unstable) | 2,500 kbps | 1,000 kbps | 200 ms |
| Offline / Flaky Connection | 0 kbps | 0 kbps | 1,000 ms |
Chrome DevTools (recommended)
Open DevTools
Right-click → Inspect, or press Ctrl+Shift+I (Windows) / Cmd+Option+I (Mac)
Simulate network conditions
- Go to the Network tab.
- Locate the Throttling dropdown (default: No throttling).
- Click Add… or Custom and enter the values from the profiles table above.
- Select your saved profile from the dropdown.
- Reload the page to test.
Simulate offline mode
In the Network tab, select Offline and reload the page. Validate fallback behaviour when no connectivity is available.
Simulate CPU throttling (device constraint)
- Go to the Performance tab.
- Click the gear/settings icon.
- Enable CPU throttling (4× or 6× slowdown).
- Observe: time to interactive, UI responsiveness, and long tasks.
Simulate low-end devices (device toolbar)
- Toggle device toolbar (Ctrl+Shift+M).
- Select a device (e.g., low-end Android).
- Combine with network throttling for a realistic low-resource test.
Firefox DevTools
- Open DevTools → Network tab.
- Use the Throttling dropdown — select presets or create a custom profile.
- Toggle Offline mode to test fallback behaviour.
Safari (Mac)
- Enable developer tools: Preferences → Advanced → Show Develop menu.
- Go to Develop → Network Link Conditioner.
- Choose a preset or create a custom profile to simulate network conditions.
Testing strategy
- Start with Slow 3G as the baseline.
- Validate extreme cases (2G and offline).
- Test mid-tier profiles (Fast 3G / Low 4G).
- Include unstable scenarios (Public Wi-Fi).
- Fix issues that break under Slow 3G first; ensure graceful degradation under 2G.
Code examples
Detect network type
// Check if the Network Information API is available
if (navigator.connection) {
// Log the effective connection type (e.g., '2g', '3g', '4g', 'wifi')
console.log('Effective network type:', navigator.connection.effectiveType);
}
Adaptive loading based on network
// Load a lightweight version for slow networks
if (navigator.connection?.effectiveType === '2g') {
// User has a slow connection — load a lighter version of the site
loadLiteVersion();
} else {
// Faster connection — load full-featured version
loadFullVersion();
}
function loadLiteVersion() {
// e.g., load smaller images, defer non-critical scripts
}
function loadFullVersion() {
// e.g., load high-res images, full scripts
}
The Developer Supplement provides practical guidance for implementing LRO principles. It covers how to optimise web performance for low-resource environments and explains why each benchmark matters.
Technical benchmarks reference
| Metric | Technical Benchmark | Tools |
|---|---|---|
| Loading & Rendering | ||
| Largest Contentful Paint (LCP) | ≤ 2.0s | Lighthouse, WebPageTest |
| First Contentful Paint (FCP) | ≤ 1.5s | Lighthouse |
| Time to First Byte (TTFB) | ≤ 500ms | WebPageTest, Chrome DevTools |
| Total Blocking Time (TBT) | ≤ 200ms | Lighthouse |
| Speed Index | ≤ 3.0s | WebPageTest |
| First CPU Idle | ≤ 3.5s | Lighthouse |
| Time to Interactive (TTI) | ≤ 5s | Lighthouse |
| Code & Assets | ||
| JavaScript Bundle Size | ≤ 150 KB gzipped | Lighthouse, Source Map Explorer |
| Critical JS | ≤ 30 KB inline/async | Chrome DevTools Coverage |
| CSS Bundle Size | ≤ 50 KB gzipped | Chrome DevTools, PurgeCSS |
| Critical CSS Inline | ≤ 15 KB | Critical, Lighthouse |
| Total Page Weight | ≤ 500 KB initial | WebPageTest, PageSpeed Insights |
| HTTP Requests | ≤ 50 requests | WebPageTest waterfall |
| Third-Party Scripts | ≤ 3 scripts, ≤ 50 KB | RequestMap, Lighthouse |
| Images & Media | ||
| Image Size | ≤ 100 KB per image | Squoosh, ImageOptim, Lighthouse |
| Above-the-Fold Images | ≤ 3 images | WebPageTest filmstrip |
| Preferred Formats | AVIF/WebP only | Lighthouse |
| Lazy Loading | 100% of non-critical images | Chrome DevTools, Lighthouse |
| Video Usage | No autoplay, ≤ 1 MB preview | Chrome DevTools, Manual Audit |
| SVGs (icons) | ≤ 5 KB each, inline | Chrome DevTools |
| Fonts | ||
| Font Size | ≤ 50 KB per family | WebPageTest, Lighthouse |
| Max Families | ≤ 2 | Chrome DevTools |
| Preload Critical Fonts | Required | Lighthouse |
| Fallbacks Defined | Required | CSS Audit, Manual |
| Design & UI | ||
| Animations | Avoid GPU-heavy, no autoplay video | Chrome DevTools Performance |
| Reduced Motion Support | prefers-reduced-motion honoured |
Manual, Lighthouse Accessibility |
| Color Contrast | WCAG AA (≥ 4.5:1) | Axe, Lighthouse Accessibility |
| Layout Stability (CLS) | ≤ 0.05 | Lighthouse, Chrome DevTools |
| Tap Targets | ≥ 48px | Axe, Chrome DevTools |
| Resilience & Usability | ||
| Keyboard Navigation | Fully supported | Axe, Manual testing |
| Text-first Mode | Usable with CSS/JS off | Manual testing |
| Offline First (Service Worker) | ≤ 1 MB cache, fallback | Lighthouse PWA, Workbox |
| Graceful Degradation | No crashes on 1 GB RAM devices | Chrome DevTools Throttling |
| Progressive Enhancement | Core usable without JS | Manual testing |
| Network Efficiency | ||
| Critical Rendering Path | ≤ 75 KB critical resources | Lighthouse, WebPageTest |
| Caching – HTML | ≤ 5 min TTL | DevTools, WebPageTest |
| Caching – Assets | ≥ 30 days TTL with versioning | DevTools, WebPageTest |
Page weight & requests
1. Total page size ≤ 500 KB (initial load)
Why it matters: In low-bandwidth environments, every extra kilobyte directly impacts load time. A 2 MB site might take 30+ seconds on 2G, causing abandonment.
How to achieve:
- Compress images (WebP/AVIF preferred).
- Enable Gzip/Brotli compression on the server.
- Minify and tree-shake CSS & JS.
- Avoid large background images/videos on first load — load them lazily.
2. ≤ 50 HTTP requests on first load
Why it matters: Each request adds round-trip latency. On 3G, latency can be 400ms+ per request, so 100 requests may mean 40 seconds of waiting before content downloads.
How to achieve:
- Combine/minify CSS & JS files where appropriate.
- Use HTTP/2 or HTTP/3 (which handles multiple streams more efficiently).
- Inline small critical assets (SVG icons, tiny CSS) instead of separate requests.
- Defer analytics, ads, and third-party widgets until the main content has loaded.
3. Inline/preload critical CSS, defer non-essential JS
Why it matters: Browsers block rendering until they fetch and parse CSS & JS. External and delayed critical resources mean users see a blank screen for longer.
How to achieve:
- Use tools like CriticalCSS or PurgeCSS to extract minimal CSS for inlining.
- Add
<link rel="preload">for fonts and critical CSS. - Add
deferorasyncattributes to script tags. - Lazy-load non-essential widgets, ads, or heavy scripts.
Performance metrics
1. First Contentful Paint (FCP ≤ 2s on 3G)
Time until the first piece of DOM content is rendered. Signals to the user that something is happening. Optimisation tips: minimise critical path resources, compress and preload fonts, use a fast CDN, reduce render-blocking CSS/JS.
2. Largest Contentful Paint (LCP ≤ 2.5s)
Time for the largest visible element to render. Measures when the main content is actually ready. Optimisation tips: optimise hero images, preload LCP assets, reduce TTFB below 600ms, avoid oversized images.
3. Time to Interactive (TTI ≤ 5s on mid-tier device)
Time until the page can reliably respond to user input. Optimisation tips: split code bundles, defer non-critical JavaScript, use web workers for heavy computations, minimise main thread work.
4. Total Blocking Time (TBT ≤ 300ms)
Total time between FCP and TTI where the main thread was blocked by long tasks (>50ms). Optimisation tips: break long JS tasks into smaller chunks, use requestIdleCallback for background work, optimise third-party scripts.
5. Cumulative Layout Shift (CLS ≤ 0.1)
Measures how much visible content unexpectedly shifts during page load. Optimisation tips: always set width/height on images and video, preload fonts to avoid FOUT, avoid dynamically inserting DOM elements above existing content, reserve space for ads and embeds.
JavaScript & resource use
1. JS bundle ≤ 150 KB gzipped (initial load)
Why it matters: Large bundles take longer to download on slow networks. Parsing and executing JS is CPU-intensive — low-tier devices may take seconds even after the download finishes.
How to achieve: Tree-shaking, code splitting, lazy-loading non-critical features, replacing heavy frameworks with lighter alternatives (e.g., Preact instead of React, native JS where possible).
2. No long tasks > 50ms
Why it matters: Long tasks block the main thread, causing UI freezes, input delays, and jank — magnified on mid-tier devices.
How to achieve: Break heavy computations into smaller chunks, use requestIdleCallback for non-urgent background work, offload CPU-heavy logic to Web Workers, reduce expensive DOM operations during load.
3. Memory stable on 512 MB RAM devices
Why it matters: High memory usage causes frequent garbage collection and crashes on entry-level smartphones common in low-resource regions.
How to achieve: Avoid memory leaks (detached DOM nodes, unremoved event listeners), use device-appropriate image sizes, keep JS variables and in-memory caches minimal.
4. Core features work with JS disabled/partial load
Why it matters: On weak networks, JS files may timeout or fail. Accessibility tools and old browsers may not execute JS.
How to achieve: Progressive enhancement — start with semantic HTML, layer JS enhancements. Ensure core navigation and content are server-rendered. Provide server-side fallbacks for forms, links, and routing.
Network resilience
1. Test on slow 3G (400 kbps, 400ms RTT)
Use Chrome DevTools → Network Throttling → Slow 3G. Use WebPageTest with Moto G4/3G profile. Add performance budgets that fail builds if page exceeds size/load thresholds.
2. Progressive rendering: content visible early
Inline critical HTML & CSS (above-the-fold). Defer non-essential JS and images. Use skeleton screens or content placeholders. Stream HTML as chunks are ready rather than as one large response.
3. Service worker caching for critical assets
Use Workbox or manual service worker setup. Cache HTML shell + essential assets (CacheFirst strategy). Apply StaleWhileRevalidate for frequently updated resources (API calls). Keep the cache size small — avoid blindly caching everything.
4. Retry/fallback for images & data fetches
For images: use <picture> with multiple formats/sizes and provide low-res placeholders as fallbacks. For fetches/API calls: implement retry logic with exponential backoff, show cached/offline data where possible, and gracefully degrade the UI ("content unavailable, try again").
Accessibility & usability
1. Keyboard-only navigation works
Why it matters: Many low-resource users rely on non-mouse input. Keyboard support also improves screen reader compatibility.
How to achieve: Ensure focus styles are always visible, maintain logical tab order, provide skip-to-content links, and ensure interactive elements (menus, forms, modals) can be operated with keyboard only.
2. Text accessible without images/CSS/JS
Why it matters: On poor connections, resources often fail to download. Text-first browsers, screen readers, and search crawlers rely on semantic HTML.
How to achieve: Use semantic HTML tags (<h1>, <p>, <button>, <nav>), provide alt text for images, ensure text contrast is high enough without CSS, never hide essential content behind client-side rendering alone.
3. Optional low-bandwidth mode (text-first)
Why it matters: Critical for users on 2G/3G, satellite internet, or expensive metered data.
How to achieve: Offer a "Low-bandwidth mode" or "Text-only mode" toggle. Auto-detect via the Save-Data HTTP header. Use conditional loading to serve only core text and small assets in this mode.
Energy & device constraints
1. Avoid autoplay video/animations on load
Why it matters: Videos and animations consume CPU, GPU, and bandwidth — on weak devices they cause lag, stutters, or crashes; on mobile they drain battery fast.
How to achieve: Disable autoplay by default; use a static poster image instead of loading video immediately; prefer CSS transitions or SVG animations over heavy JS/Canvas effects; give users explicit "Play video" control.
2. Minimal CPU/GPU-intensive tasks
Why it matters: Low-end devices have weak CPUs/GPUs, often without hardware acceleration. Heavy computation leads to high battery drain and poor responsiveness.
How to achieve: Avoid infinite loops or constant polling; minimise reflows and repaints; avoid large shadows, blurs, or filters that trigger GPU acceleration; aim for a stable 30–60 FPS with minimal dropped frames.
3. Works on low-end Android (emulator/device test)
Why it matters: The majority of users in low-resource regions browse on low-end Android phones. Sites that feel fine on MacBooks or flagship iPhones may be unusable on these devices.
How to achieve: Test with Chrome DevTools → CPU throttling (4× or 6×) + network throttling. Use emulated Android Go devices (Moto E, Nokia C series, etc.). Run Lighthouse in simulated low-end hardware mode.
Testing & tooling
1. Run Lighthouse with throttling (3G / mid-tier mobile)
In Chrome DevTools → Lighthouse tab, set Network to Slow 3G (400 kbps, 400ms RTT) and CPU to 4× or 6× slowdown with Mobile emulation. Pay attention to FCP, LCP, TTI, CLS, and JavaScript bundle sizes.
2. Run WebPageTest (2G/3G, Moto G4 profile)
Configure WebPageTest with device Moto G4 (or similar), connection 2G/3G or custom bandwidth, and a location representative of your users (India, Africa, LATAM). Review waterfall charts for large/slow assets and use the filmstrip view to check how quickly content becomes visible.
3. Monitor Core Web Vitals (PageSpeed Insights / Search Console)
Run PageSpeed Insights regularly to compare lab vs field results. Use Search Console → Core Web Vitals report for long-term tracking. Segment performance by device type and region. Thresholds: FCP ≤ 2s, LCP ≤ 2.5s, CLS ≤ 0.1, TBT ≤ 300ms.
How to measure additional metrics
Data Cost per Page Load
Open Chrome DevTools → Network tab. Enable "Disable cache" and throttle to Slow 3G / 2G. Reload the page and check Transferred or Total bytes. Record: total MB downloaded (HTML + CSS + JS + images + fonts + APIs).
Repeat Visit Data Usage
Load page once, then reload with cache enabled. Check Network tab → Transferred size (excluding "from disk cache"). Record: KB transferred on second load.
Image Bytes Ratio
Filter the Network tab by Img. Sum image bytes and divide by total page bytes. Formula: Image Bytes / Total Bytes × 100.
Partial Load Usability
Disable JavaScript (DevTools → Settings → Disable JS). Reload and count total key content sections vs visible/usable sections. Formula: Visible core sections / Total core sections × 100.
Retry Friendliness
Throttle to Slow 3G, simulate a network drop, and observe auto-retries, error messages, and exponential backoff behaviour. Score: Yes / Partial / No.
Peak Memory Usage
Open Chrome Performance → Record → Reload page → Stop recording. Inspect the Memory graph. Record: peak MB usage.
JS Execution Time
Run Lighthouse and check Total Blocking Time and JS execution time. Or inspect the CPU flame chart in the Performance tab. Record: seconds of JS execution.
DOM Node Count
Run document.getElementsByTagName('*').length in the DevTools Console. Record: number of DOM nodes (target ≤ 800).
CPU Wakeups per Minute
In Chrome Performance, record an idle page for 1 minute and count CPU spikes. Record: wakeups/minute (target ≤ 5).
Network Requests After Idle
Load the page, wait 30–60 seconds, and observe new requests in the Network tab. Record: None / Minimal / Frequent.
Old Browser Support
Test on Android 8 / Chrome 80 in BrowserStack or Sauce Labs. Verify the page loads and core content is visible. Score: Full / Partial / Broken.
No-JS Mode Coverage
Disable JS, reload, and count visible content sections. Record: percentage (target ≥ 80%).
Time to First Meaningful Text
Run Lighthouse and observe First Contentful Paint, then validate visually. Record: seconds (target ≤ 1s).
Blank Screen Time
Run WebPageTest video capture and observe video frames until content appears. Record: milliseconds (target ≤ 500ms).
Low-Data Mode Toggle
Look for the toggle in the UI, test it, and verify a reduced payload. Score: Yes / Hidden / No.
Data Usage Disclosure
Trigger large content and observe whether a warning or message is displayed. Score: Always / Sometimes / Never.
Implementation guidance
Practical steps
- Define performance budgets based on LRO benchmarks.
- Integrate measurement into CI/CD pipelines.
- Test on slow networks and low-end devices.
- Monitor real-user metrics continuously.
- Prioritise fixes based on impact and weighting.
Architecture choices
- Use a CDN for faster delivery.
- Implement caching strategies.
- Design APIs for low latency.
Runtime behaviour
- Track performance metrics in real time.
- Detect regressions automatically.
- Adapt experience based on network/device.
Decision guidance
- Fix high-weight metrics first (LCP, page weight, JS size).
- Address usability and resilience next.
- Optimise polish only after core performance is stable.
The Developer supplement tab has more details on how to optimise these metrics.
Do / Don't
Do
- Test on slow networks and real devices.
- Define clear performance budgets.
- Monitor both lab and real-user metrics.
- Measure UX alongside performance.
- Continuously track regressions.
Don't
- Rely only on desktop testing.
- Ignore low-end device performance.
- Optimise only for the Lighthouse score.
- Skip accessibility and usability testing.
- Assume one-time testing is enough.
Checklist
Tools
- Lighthouse
- Chrome DevTools (Network, Performance, Memory)
- WebPageTest
- PageSpeed Insights
- Search Console (Core Web Vitals)
- Axe (accessibility testing)
- BrowserStack (device testing)
Related topics
- Network optimisation
- Caching strategies
- JavaScript strategy
- Rendering strategies
- Resilience & offline patterns
- Accessibility