Modern web applications rely on JavaScript that is still mostly single-threaded. These modern frameworks have increasing resource requirements, but they’re often used on low-end/mid-tier Android devices or older notebooks whose single-thread performance isn't comparable to the machines that developers work on.
1x = M2 Mac baseline; higher numbers ~ that many times slower.
Most iPhones land around 1x–2x (near desktop-class), with a smaller share at 4x and very little at 8x–16x. iOS skews faster than Android overall, but older models still benefit from testing at 4x to catch long tasks.
Usual Android audience clusters at 2x–4x with a noticeable tail at 8x–16x. In practice, code that feels snappy on a dev laptop can easily bottleneck on Android unless it stays responsive under at least a 4x slowdown.
When a device's CPU is overwhelmed, the user experience suffers directly. This CPU contention is a primary cause of poor responsiveness; every click, tap, or keypress can be delayed because the browser's main thread is too busy to process user input. This exact problem is what Google's Interaction to Next Paint (INP) metric is designed to measure. A high INP score is a clear sign that a page is struggling to provide timely visual feedback to user interactions, sometimes because the CPU is maxed out.
However, until now, developers lacked a standardized, privacy-preserving way to proactively gauge this CPU load and adapt the application in real time before the user feels this lag. This is where the Compute Pressure API comes in.
What is the Compute Pressure API?
The Compute Pressure API is a new web API (currently an experimental Candidate Recommendation spec at W3C as of August 2025) that allows websites to observe the pressure on CPU usageand respond to changes. By monitoring this signal, an app can trade off resource usage for a better user experience when the system is under strain. The Compute Pressure API reports "pressure” statesrather than exact metrics, this design protects user privacy (preventing fingerprinting via precise hardware stats) while still giving developers enough information to make decisions . Under the hood, the browser can use whatever hardware telemetry (CPU load, thermal sensors, throttling status, etc.) to determine these states, but the site only sees an abstracted value.
In practical use, the Compute Pressure API is exposed via a JavaScript interface called PressureObserver . Websites can register a callback to be notified whenever the system’s pressure state changes (e.g. from "fair” to "serious” pressure). The API is asynchronous and observer based, much like other modern observers (e.g. IntersectionObserver or PerformanceObserver ), so it delivers updates in a non-blocking way whenever thresholds are crossed.
Pressure States Explained
The specification defines an enum PressureState with four possible values:
- Nominal: The system is under minimal load. Current workloads are light enough that the CPU can run at a lower clock speed to save power . This is the "all clear” state, indicating plenty of headroom.
- Fair: The system is doing fine, with everything running smoothly. There’s moderate load but it can handle additional work without issues . Think of this as normal operating conditions.
- Serious: The system is under significant pressure, although still managing. It’s getting close to its limits: CPU frequencies are likely maxed out (especially on battery power) and temperatures are high (but not yet causing throttling) . In this state, if you keep adding more work, the system may soon tip into the highest pressure level.
- Critical: The system is at the verge of its limits . While it might not yet be actively throttling, this level of load isn’t sustainable for long. It’s essentially a last warning that if the current workload continues, the device will start throttling or otherwise degrade performance to protect itself. For web apps, reaching "critical” is a sign to immediately lighten the workload if possible
These states provide a simple, semantic description of system load. For example, instead of saying "CPU usage is at 95% on 8 cores with temperature at 90°C,” the browser might simply report state = "critical" , telling the app that the overall compute pressure is at a critical level. This abstraction avoids exposing exact values while still conveying the urgency to the app.
Use Cases and Benefits
The primary benefit of the Compute Pressure API is adaptive performance optimization. By receiving pressure updates, web apps can proactively adjust their behavior to maintain a good user experience.
Switch from Video Ads to image ads: A web app could monitor pressure and remove video ads and replace them with image ads to save on CPU.
Complex UIs and data visualizations: Interactive web apps (dashboards, maps, etc.) could render simpler placeholders or pause non-essential updates when pressure is high. For instance, a data-heavy app might defer rendering large charts or hide non-critical animations if the system is nearing its limits, resuming them once pressure returns to nominal.
Video conferencing: A web meeting app could monitor pressure and reduce its load when the device is struggling. For instance, if pressure rises to serious or critical, the app might lower the video resolution, drop the frame rate, or show fewer video feeds (e.g. switch to showing only the active speaker) . This prevents stuttering, audio cuts, or a total UI freeze due to an overwhelmed CPU. When pressure eases back to nominal/fair, the app can gradually re-enable video streams or effects.
General user experience: Any app doing background processing can use pressure signals to modulate that work. If the system is nominal, it might perform tasks at full speed; but if it enters critical, the app could postpone or chunk heavy tasks to avoid contributing to a potential unresponsive browser. The goal is to prevent the scenario where the entire device becomes unresponsive or too hot/loud because the web app pushed it too far.
In short, the Compute Pressure API enables graceful degradationand progressive enhancementbased on device capabilities at the moment. Rather than a one-size-fits-all performance profile, web apps can tailor their resource usage to current conditions. This is similar to how adaptive bitrate streaming adjusts video quality to network bandwidth, here, we are adapting to CPU bandwidth.
Using the Compute Pressure API
Using the API in code is straightforward. It follows an observer pattern: you create a PressureObserver with a callback, then call observe() on a given source (like "cpu" ). The callback will be invoked whenever the pressure state changes (or periodically, within some sampling interval). Each invocation provides an array of PressureRecord entries, with each record containing a state (one of the four states above), a timestamp, and the source type.
Here’s a basic example of how a web app might use PressureObserver to monitor CPU pressure and adjust a video conferencing UI accordingly:
// Define a callback to handle pressure updates
function onPressureChange(records) {
// get the most recent update
const lastRecord = records[records.length - 1];
console.log(`Current pressure state: ${lastRecord.state}`);
switch (lastRecord.state) {
case "critical":
// Critical pressure: aggressively reduce workload
// e.g. pause incoming video streams
disableAllVideoFeeds();
break;
case "serious":
// Serious pressure: somewhat reduce workload
// e.g. turn off background blurs/filters
disableVideoEffects();
break;
case "fair":
case "nominal":
// Low pressure: can enable full experience
// e.g. restore streams and effects
enableAllVideoFeatures();
break;
}
}
if ('PressureObserver' in window) {
// Create a PressureObserver and
// start observing CPU pressure
try {
const observer = new PressureObserver(onPressureChange);
// sample roughly every 1s
await observer.observe("cpu", { sampleInterval: 1000 });
} catch (err) {
console.error("Compute Pressure API failed to start:", err);
}
} else {
// The app will have to run without adaptive features.
console.log("Compute Pressure API is not supported in this browser.");
}
Get our monthly web performance news roundup!
No spam - everything you need to know about in web performance with exclusive insights from our team.
A few things to note from this snippet:
- We check lastRecord.state. The callback’s records array may contain multiple entries if the state changed several times since the last callback invocation, but the last one is the current state. In this example, we simply react to the latest state and ignore earlier entries.
- The observe("cpu", { sampleInterval: 1000 }) call begins observing CPU pressure, with a requested sampling interval of 1000ms. The API allows you to specify how frequently you’d like updates via this sampleInterval option. The browser may cap or adjust the actual sampling rate for efficiency and privacy. In practice the one update per second is common and was used in Chrome’s origin trials.
- We wrap the observe call in a try/catch . This is important because observe() will throw a NotSupportedError exception if the requested source isn’t available or throw a NotAllowedError when disallowed by Permissions Policy. A basic feature detection can also be done via checking if ("PressureObserver" in window) before even trying to use it .
- You can also use the PressureObserver.knownSources to see what is available for observing. Chrome 125 only supports CPU.
- The PressureObserver is available not only on the main thread ( window context) but also in Web Workers and Shared Workers. This means you could offload the pressure monitoring to a worker if desired. One notable exception: it’s not available in Service Workers, since they have no window or worker thread in the same sense.
- If you want to use the Compute Pressure API inside an <iframe>, the embedding page must explicitly allow it via the Permissions Policy. Example: <iframe src="..." allow="compute-pressure"></iframe>. Or allow it via the Permissions-Policy header
Best Practices
Use pressure signals proactively, but judiciously. The intent of this API is to avoid bad experiences before they happen. If you see the state elevate to "serious", start dialing things down to prevent reaching "critical". Users will appreciate that your app "just works” without hitting obvious performance hiccups.
At the same time, avoid overreacting or oscillating behavior. Minor, brief jumps in pressure might not warrant immediately turning off half your features. It’s wise to introduce some hysteresis or smoothing in your adaptation logic. For instance, you might require the pressure to stay at "serious" for a few seconds before making a big change, and similarly only re-enable features after pressure has been back at "fair" for a bit. The API will proactively signal rising and easing pressure, so you can know not just when things get worse, but also when they improve. Use that to restore functionality so users get the best experience their device can handle at any given time.
What This API Is NOT
To use the Compute Pressure API effectively, it's just as important to understand its limitations and what it isn't designed to do.
- It is not a replacement for writing performant code. Your first line of defense against performance issues should always be efficient algorithms, sensible data handling, and optimizing critical code paths. The Compute Pressure API is a tool for graceful degradation when the user's system is under strain, not a license to ship bloated JavaScript and hope the API will clean up the mess.
- It is not a precise benchmarking tool. The API provides abstract states (nominal, fair, serious, critical), not a specific CPU percentage or clock speed. If you need to measure the execution time of your own functions, you should continue to use high-resolution timers like the Performance API (performance.now()).
- It is not a comprehensive system monitor. As of its initial release, the API is focused exclusively on CPU pressure. It cannot tell you if the system is running out of memory (RAM), if the GPU is overloaded, or if network I/O is a bottleneck. While future versions of the spec may introduce other sources, for now, you should treat this purely as a signal about the state of the central processor.
Browser Support and Current Status as of August 2025
Browser | Desktop Support | Mobile Support | Notes |
---|---|---|---|
Chrome / Edge | ✅ Supported (125+) | ❌ Not Supported | Android support has been deprioritized due to unavailable telemetry post-Android 11. |
Opera | ✅ Supported (111+) | ❌ Not Supported | |
Firefox | ❌ Not Supported | ❌ Not Supported | No public signals of intent to implement. |
Safari | ❌ Not Supported | ❌ Not Supported | No public signals of intent to implement. (All iOS browsers use WebKit). |
Conclusion and Outlook
This is still an early technology. As of 2025, it’s essentially a Chrome-only feature, and developers must implement it as a progressive enhancement. We should also recognize that the notion of "compute pressure” may evolve - future versions of the spec might introduce new source types (for example one could imagine GPU or memory pressure in the future). The success of Compute Pressure API will depend on real-world usage and feedback. Developers are encouraged to experiment with it in Chrome, report issues or suggestions to the W3C and Chromium teams, and contribute to a broader understanding of how web apps can best cooperate with device resources.
In the bigger picture, the Compute Pressure API is part of a trend toward responsive web performance - not in the CSS layout sense, but in adapting to the user’s platform capabilities dynamically. It complements other tools like responsive design, network information, battery status, and performance observers, adding a crucial piece: awareness of when the device itself is under strain. Armed with this knowledge, web apps can be both ambitious (using all available power when possible) and prudent (throttling back when necessary) . The end goal is a web that delivers high-quality experiences optimized not just for the "average” device, but tuned to each user’s context in the moment.