In brief: use navigator.cpuPerformance to choose the initial profile, then use PressureObserver to monitor the cpuWhen the state is serious or critical, disable non-essential effects and tasks; if the API is unavailable or does not work, use a predefined light or balanced profile.
This approach supports an adaptive web experience: powerful machines can retain the full set of effects, while less capable devices can reduce animations, background video, update frequency, or secondary processing. This is not an accurate benchmark and does not guarantee that every site will be faster. You must still optimize JavaScript, images, and network usage as usual.
Distinguish CPU capability from CPU pressure
| Signal | What question does it answer? | What should it be used for? |
|---|---|---|
navigator.cpuPerformance | Which CPU capability tier does the device belong to? | Choose the initial profile when the page initializes. |
PressureObserver | How much pressure is the CPU under right now? | Reduce or restore non-essential features while the page is running. |
The CPU Performance API provides a relatively stable signal about a performance tier, while the Compute Pressure API reflects a dynamic state that may be affected by other tabs or applications. States such as nominal, fair, serious and critical are not specific CPU percentages (according to developer.mozilla.org).
Therefore, do not write a condition such as “enable effects when CPU usage is below 40%.” Use the tier to choose the initial configuration, then use the pressure state to pause secondary features. Chrome 152 introduced the CPU Performance API through navigator.cpuPerformance; the reported tier may be overridden by the user or administrator in some environments, so applications must not treat this value as conclusive evidence about the hardware (according to developer.chrome.com).
Prepare profiles before reading the API
The API is useful only when the website already has features that can be scaled back. Start with three clearly defined profiles:
| Profile | Behavior | When to use it |
|---|---|---|
light | Disable decorative animations and background video, stop unnecessary background tasks, and refresh less frequently. | Low or unknown tier, or CPU in a serious state. |
balanced | Keep effects brief, load data only when needed, and limit secondary updates. | A safe fallback for most cases where there is not enough signal. |
full | Keep effects and secondary tasks when they do not reduce interaction responsiveness. | High tier and CPU pressure at an acceptable level. |
Keep content reading, text entry, navigation, form submission, and post-action feedback intact. In a dashboard, you can disable chart animations and reduce the refresh frequency, but you should not hide filters or delay button responses.
If the page is loading many animated images, converting GIFs to video to reduce file size is a separate optimization approach. The CPU Performance API does not replace reducing resource sizes or fixing JavaScript that is already too heavy.
Implement the initial profile and fallback
Run the following JavaScript in the page’s browser-side code after the DOM is ready or at the end of the HTML document. Replace the body of updateNonCriticalData() with the application’s actual task. The tier thresholds in this example are only starting points; adjust them based on the actual cost of each feature.
const profiles = {
light: {
effects: false,
backgroundWork: false,
refreshInterval: 15000,
},
balanced: {
effects: true,
backgroundWork: false,
refreshInterval: 10000,
},
full: {
effects: true,
backgroundWork: true,
refreshInterval: 5000,
},
};
let activeProfileName = 'balanced';
let backgroundTimer = null;
async function updateNonCriticalData() {
// Thay bằng việc tải hoặc tính toán không thiết yếu của ứng dụng.
}
function setBackgroundWorkEnabled(enabled, interval) {
if (backgroundTimer !== null) {
clearInterval(backgroundTimer);
backgroundTimer = null;
}
if (enabled) {
backgroundTimer = window.setInterval(
updateNonCriticalData,
interval
);
}
}
function applyProfile(profileName) {
const profile = profiles[profileName];
if (!profile) return;
activeProfileName = profileName;
document.documentElement.classList.toggle(
'low-power-mode',
!profile.effects
);
setBackgroundWorkEnabled(
profile.backgroundWork,
profile.refreshInterval
);
}
function getInitialProfile() {
if (!('cpuPerformance' in navigator)) {
return 'balanced';
}
const tier = navigator.cpuPerformance;
if (!Number.isInteger(tier) || tier === 0) {
return 'balanced';
}
// Đây là ngưỡng minh họa; kiểm tra lại bằng chi phí thật của ứng dụng.
return tier <= 2 ? 'light' : 'full';
}
applyProfile(getInitialProfile());
Profile balanced is the safe fallback in this example, while profile light is used when the tier is identified as low. If your product prioritizes reducing load over the default visual presentation, you can change the fallback to light; check support again before deployment.
Monitor CPU pressure without making the interface flicker
Place the following code immediately after the profile code. This pattern requires a high state to occur consecutively before switching to light, and requires several normal readings before restoring the initial profile. This mechanism is called delay or hysteresis; it prevents state changes in response to a brief signal.
function watchCpuPressure() {
if (!('PressureObserver' in window)) {
return;
}
const initialProfile = getInitialProfile();
let seriousSamples = 0;
let normalSamples = 0;
const observer = new PressureObserver((records) => {
const latest = records[records.length - 1];
if (!latest) return;
const pressureIsHigh =
latest.state === 'serious' || latest.state === 'critical';
if (pressureIsHigh) {
seriousSamples += 1;
normalSamples = 0;
if (seriousSamples >= 3) {
applyProfile('light');
}
return;
}
seriousSamples = 0;
normalSamples += 1;
if (normalSamples >= 5) {
applyProfile(initialProfile);
}
});
observer.observe('cpu', { sampleInterval: 1000 }).catch((error) => {
console.warn('Không thể theo dõi áp lực CPU:', error);
});
}
watchCpuPressure();
sampleInterval: 1000 is only an illustrative value. If the browser does not accept the cpu source or observation options, the call to observe() may be rejected; in that case, continue using the profile applied in the previous step. This error does not need to be treated as one that blocks the entire page.
Disable only non-essential components with CSS and JavaScript
CSS is suitable for decorative elements, but hiding an element does not mean that JavaScript has stopped processing. Add the following rules to the page’s CSS file:
.low-power-mode .decorative-animation,
.low-power-mode .background-video {
display: none;
}
.low-power-mode .chart {
transition: none;
}
For background tasks, stop the timers or skip unnecessary computation. The setBackgroundWorkEnabled() function above clears the timer before creating it again. If the actual task uses requestAnimationFrame, Web Worker or a charting library, add the corresponding stop operation instead of merely adding a CSS class.
If the user has enabled reduced motion or manually selected a power-saving mode, that choice should take precedence. Do not allow the automatic restoration of the full profile to override an accessibility preference or an explicit user setting.
Check HTTPS, browser support, and iframes

- Run in a secure context: a production website should use HTTPS with a valid certificate. During local development,
localhostis generally more suitable than opening the HTML file directly. - Check feature support: use
'cpuPerformance' in navigatorand'PressureObserver' in window, rather than inferring support from the browser’s name or version alone. - Keep the fallback: unsupported browsers must still be able to read the content, navigate the site, and complete the primary task.
- Check iframes: if the code runs in an iframe, check the origin and Permissions Policy before concluding that the API is failing.
- Minimize data collection: use the tier only to adjust the on-site experience; do not turn this signal into a device-identification profile.
The Compute Pressure API currently has uneven coverage across major browsers, and MDN records it as having limited availability. Therefore, it should be treated as progressive enhancement rather than a prerequisite for loading the page (according to developer.mozilla.org).
Verify the results before release
- Check the initial state: open the page in environments with and without the APIs; confirm the selected profile, the
low-power-modeclass, and the corresponding timers. - Test the low profile: use the CPU-tier override mechanism in Chrome 152 if your test environment provides that option. Do not use this option as evidence about every real-world device.
- Test dynamic pressure: in a safe test environment, confirm that sufficiently high pressure disables effects and actually stops background tasks.
- Measure the workload: use Chrome DevTools Performance to inspect long tasks, JavaScript activity, the number of repaints, and the update frequency before and after applying the profile.
- Test restoration: confirm that restoring the profile does not lose form state, create duplicate network requests, or make the interface flicker.
- Test the primary task: reading, data entry, navigation, and form submission must work in the low profile.
The success criterion is not “the tier was read,” but that the low profile actually removes some non-essential work while users can still complete their tasks. If an icon is merely hidden with CSS while the code continues computing at the same frequency, the implementation has not met its objective.
Common errors and rollback
- Treating the tier as a benchmark: the tier is only a classification group; do not use it to promise a specific execution time.
- Reading it only once: the initial capability does not reflect pressure caused by other applications, other tabs, or thermal throttling.
- Disabling primary functionality: reduce decorative elements and secondary tasks first; the low profile must remain usable.
- Switching profiles too quickly: use consecutive readings or a minimum duration as shown in the example to prevent state flicker.
- Failing to handle errors
observe(): keep a fallback profile when the sourcecpuis not supported. - Override user choices: accessibility settings and manual choices must take precedence over automated decisions.
If the automated logic causes problems, the safe rollback is to stop calling watchCpuPressure() but retain the initial profile and feature checks. If that profile still causes problems, set activeProfileName it to balanced, disable non-essential background tasks individually, and check the main flow again. Restore the profile full only after confirming that the effects do not reduce responsiveness.
A Practical Rollout Strategy
Start with an easily observable feature, such as a background video, chart animation, or update timer. Record the state before integration, deploy the light profile, measure the task again, and test the primary task. Once the fallback path is stable, expand to image processing, data preloading, or more CPU-intensive JavaScript tasks.
Do not create too many quality levels at the outset. Three profiles light, balanced and full are generally easier to test, but the thresholds and contents of each profile must be based on the application's actual costs. The API provides signals only; the development team remains responsible for deciding which features to disable.
Conclusion
The CPU Performance API is suited to selecting the initial experience level, while the Compute Pressure API is suited to responding to changes while the page is running. A safe implementation requires feature detection, HTTPS, a fallback profile, protection against constant state switching, respect for user choices, and verification that non-essential tasks are actually reduced.
Treat this as a progressive enhancement layer, not as an accurate method for measuring device speed. If the browser does not provide the signal, the website must still function normally with a balanced or light profile.
Reference source
- New in Chrome 152 — Chrome for Developers.
- Chrome 152 | Release notes — Chrome for Developers.
- Compute Pressure API – Web APIs — MDN Web Docs.
- Compute Pressure API: Browser compatibility — MDN Web Docs.
- WICG/cpu-performance — Web Incubator Community Group.
- Compute Pressure API — Chrome for Developers.

