Chrome MV3 extension causes browser lag when loaded — how can I profile content scripts and service worker timers?

Chrome MV3 extension causes browser lag when loaded — how can I profile content scripts and service worker timers?

I’m trying to debug a Chrome Manifest V3 extension I built. I have already narrowed the issue down to the extension itself:

What I tested:
- Chrome runs normally with the extension disabled.
- Windows/Chrome start feeling laggy shortly after loading the unpacked extension.
- The repo has been redacted and pushed publicly here:
https://github.com/jacobsscoots/CTL-Redacted
- I removed real company names, internal domains, private URLs, and personal paths.

I’m not asking anyone to rewrite the extension. I’m trying to learn the correct way to profile it and identify the slow part.

The extension has:
- Multiple content scripts.
- Some scripts running with all_frames: true.
- MutationObserver usage.
- Polling/timers.
- A MV3 service worker.
- chrome.alarms usage.
- DOM scans using querySelector/querySelectorAll.
- Scripts injected into large single-page web apps.

The main thing I’m unsure about is whether the lag is more likely caused by:

  1. Content scripts being injected into too many frames.
  2. MutationObservers firing too often.
  3. Polling/timers repeatedly scanning the DOM.
  4. Service worker alarms/message passing.
  5. Something else in the MV3 lifecycle.

Example of the type of pattern I’m worried about:

const observer = new MutationObserver(() => {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(scanPage, 250);
});

observer.observe(document.body, {
childList: true,
subtree: true
});

setInterval(scanPage, 5000);

function scanPage() {
const nodes = document.querySelectorAll("div, span, button, input");

for (const node of nodes) {
// Reads text/attributes and updates extension state
}
}

What I’ve tried so far:
- Disabled the extension and confirmed Chrome runs fine.
- Created a redacted public version of the repo.
- Looked for obvious risky patterns such as all_frames, MutationObserver, setInterval, querySelectorAll, and chrome.alarms.
- I’m planning to use Chrome Task Manager and DevTools Performance, but I’m not sure what the best order is.

My questions:

  1. What is the best way to profile an unpacked Chrome MV3 extension?
  2. Should I start with Chrome Task Manager, DevTools Performance, or the service worker inspector?
  3. How can I tell which content script is causing the lag?
  4. Are MutationObserver + all_frames + repeated DOM scans common causes of browser-wide lag?
  5. What small changes should I test first before rewriting anything?

Any guidance on how to approach the debugging would be appreciated.

Github link for the repo: https://github.com/jacobsscoots/CTL-Redacted

u/Zealousideal_Weird82 — 5 days ago

Chrome MV3 extension makes Chrome/Windows laggy when loaded — how should I profile content scripts, MutationObservers, and timers?

I’m building a personal Chrome MV3 extension. Chrome and my PC run normally when the extension is disabled, but as soon as I load the unpacked extension, Chrome starts feeling laggy/heavy.

I’m not asking anyone to debug private production code. I’ve redacted the real domains and replaced them with fake hosts.

Setup:

  • Chrome MV3 extension
  • Windows
  • Unpacked extension loaded through chrome://extensions
  • Content scripts injected on several specific web apps
  • Some content scripts use all_frames: true
  • Some scripts use MutationObserver
  • Some scripts use polling intervals, for example 2s/3s/5s/10s
  • Service worker has recurring alarms, including a 1-minute alarm
  • Disabling the extension fixes the lag

What I’m trying to find:

  1. How to identify which content script/service worker path is causing CPU/memory usage.
  2. Whether all_frames: true plus DOM scanning/MutationObservers is a likely cause.
  3. Best way to profile an unpacked MV3 extension.
  4. What patterns to avoid in content scripts that run on large SPA pages.

Minimal redacted manifest shape:

{
  "manifest_version": 3,
  "name": "Redacted Extension",
  "version": "1.0",
  "permissions": ["storage", "scripting", "tabs", "alarms", "webNavigation"],
  "host_permissions": [
    "https://app1.example.com/*",
    "https://app2.example.com/*"
  ],
  "background": {
    "service_worker": "service_worker.js",
    "type": "module"
  },
  "content_scripts": [
    {
      "matches": ["https://app1.example.com/*"],
      "js": ["content-a.js"],
      "all_frames": true,
      "run_at": "document_end"
    },
    {
      "matches": ["https://app2.example.com/*"],
      "js": ["content-b.js"],
      "all_frames": true,
      "run_at": "document_end"
    }
  ]
}

Example pattern I’m worried about:

const observer = new MutationObserver(() => {
  clearTimeout(debounceTimer);
  debounceTimer = setTimeout(scanPage, 250);
});

observer.observe(document.body, {
  childList: true,
  subtree: true
});

setInterval(scanPage, 5000);

function scanPage() {
  const nodes = document.querySelectorAll("div, span, button, input");
  for (const node of nodes) {
    // reads text/attributes and updates extension state
  }
}

What should I check first? Should I profile through Chrome Task Manager, DevTools Performance, chrome://extensions service worker inspection, or another tool?

Github repo link: https://github.com/jacobsscoots/CTL-Redacted

reddit.com
u/Zealousideal_Weird82 — 5 days ago

Chrome MV3 extension makes Chrome/Windows laggy when loaded — how should I profile content scripts, MutationObservers, and timers?

I’m building a personal Chrome MV3 extension. Chrome and my PC run normally when the extension is disabled, but as soon as I load the unpacked extension, Chrome starts feeling laggy/heavy.

I’m not asking anyone to debug private production code. I’ve redacted the real domains and replaced them with fake hosts.

Setup:

  • Chrome MV3 extension
  • Windows
  • Unpacked extension loaded through chrome://extensions
  • Content scripts injected on several specific web apps
  • Some content scripts use all_frames: true
  • Some scripts use MutationObserver
  • Some scripts use polling intervals, for example 2s/3s/5s/10s
  • Service worker has recurring alarms, including a 1-minute alarm
  • Disabling the extension fixes the lag

What I’m trying to find:

  1. How to identify which content script/service worker path is causing CPU/memory usage.
  2. Whether all_frames: true plus DOM scanning/MutationObservers is a likely cause.
  3. Best way to profile an unpacked MV3 extension.
  4. What patterns to avoid in content scripts that run on large SPA pages.

Minimal redacted manifest shape:

{
  "manifest_version": 3,
  "name": "Redacted Extension",
  "version": "1.0",
  "permissions": ["storage", "scripting", "tabs", "alarms", "webNavigation"],
  "host_permissions": [
    "https://app1.example.com/*",
    "https://app2.example.com/*"
  ],
  "background": {
    "service_worker": "service_worker.js",
    "type": "module"
  },
  "content_scripts": [
    {
      "matches": ["https://app1.example.com/*"],
      "js": ["content-a.js"],
      "all_frames": true,
      "run_at": "document_end"
    },
    {
      "matches": ["https://app2.example.com/*"],
      "js": ["content-b.js"],
      "all_frames": true,
      "run_at": "document_end"
    }
  ]
}

Example pattern I’m worried about:

const observer = new MutationObserver(() => {
  clearTimeout(debounceTimer);
  debounceTimer = setTimeout(scanPage, 250);
});

observer.observe(document.body, {
  childList: true,
  subtree: true
});

setInterval(scanPage, 5000);

function scanPage() {
  const nodes = document.querySelectorAll("div, span, button, input");
  for (const node of nodes) {
    // reads text/attributes and updates extension state
  }
}

What should I check first? Should I profile through Chrome Task Manager, DevTools Performance, chrome://extensions service worker inspection, or another tool?

Github link for the repo is: https://github.com/jacobsscoots/CTL-Redacted

reddit.com
u/Zealousideal_Weird82 — 5 days ago