# Badge updates do not trigger excessive background CPU usage

- **Pattern:** `ab-001369` (`extension-ux-performance.badge-notifications.badge-cpu-usage`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001369
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001369)

## Why it matters

Badge update calls fired on every high-frequency browser event — `webRequest.onCompleted`, `tabs.onUpdated`, or sub-5-second polling — create continuous background CPU load even when the user is doing nothing extension-related. ISO 25010:2011 performance-efficiency.resource-utilisation treats unnecessary background CPU consumption as a defect. On laptops, this translates directly to battery drain; on lower-end hardware it causes system-wide slowdown. Chrome surfaces extensions that abuse background resources in its Task Manager, leading to removal.

## Severity rationale

Medium because unbounded badge update frequency drains battery and CPU continuously, but the impact is gradual and not immediately catastrophic.

## Remediation

Debounce badge updates so high-frequency trigger events coalesce into at most one update per 500ms, and skip the `setBadgeText` call entirely when the value has not changed.

```js
let currentBadgeText = '';
let badgeUpdateTimer = null;

function scheduleBadgeUpdate() {
  clearTimeout(badgeUpdateTimer);
  badgeUpdateTimer = setTimeout(async () => {
    const count = await computeCount();
    const newText = count > 0 ? String(count) : '';
    if (newText !== currentBadgeText) {
      currentBadgeText = newText;
      chrome.action.setBadgeText({ text: newText });
    }
  }, 500);
}
```

For polling patterns, use `chrome.alarms` with a minimum 30-second interval and add idle detection via `chrome.idle` to pause updates when the system is idle.

## Detection

- **ID:** `badge-cpu-usage`
- **Severity:** `medium`
- **What to look for:** Examine how frequently the badge is updated. Look for patterns that update the badge on very high-frequency events: every `webRequest` event, every `onMessage`, every `tabs.onUpdated`, or on a very short polling interval (under 5 seconds). Each `chrome.action.setBadgeText` call has overhead. Check for redundant badge updates — setting the badge to the same value it already has. Count all instances found and enumerate each.
- **Pass criteria:** Badge updates are infrequent relative to their trigger events. High-frequency events are debounced before triggering badge updates. No unnecessary updates when the value has not changed. Polling intervals for badge-relevant data are reasonable (30 seconds or more). At least 1 implementation must be confirmed.
- **Fail criteria:** Badge update logic fires on every high-frequency event without debouncing. Badge is updated with the same value it already has (no change check before calling `setBadgeText`). Polling interval for badge data is shorter than 5 seconds with no idle detection.
- **Skip (N/A) when:** The extension does not use the badge API.
- **Detail on fail:** Describe the frequency issue. Example: `"setBadgeText called on every chrome.webRequest.onCompleted event — fires 50-200 times per minute during normal browsing"` or `"Background polls for badge data every 2 seconds with no idle detection or caching."`
- **Remediation:** Debounce badge updates and skip redundant calls:

  ```js
  let currentBadgeText = '';
  let badgeUpdateTimer = null;

  function scheduleBadgeUpdate() {
    clearTimeout(badgeUpdateTimer);
    badgeUpdateTimer = setTimeout(async () => {
      const count = await computeCount();
      const newText = count > 0 ? String(count) : '';
      if (newText !== currentBadgeText) {
        currentBadgeText = newText;
        chrome.action.setBadgeText({ text: newText });
      }
    }, 500);  // Debounce: update at most every 500ms
  }
  ```

## External references

- iso-25010 performance-efficiency.resource-utilization

Taxons: performance, cost-efficiency

HTML version: https://auditbuffet.com/patterns/ab-001369
