·8 min read·

Chrome Manifest V3: what just changed, what just broke.

Google is enforcing Manifest V3 across every Chrome extension. Five years after the proposal, the transition is real, painful, and uneven. Here's the practical state of it.

Google announced Manifest V3 in 2018. It's now 2024 and the migration deadline is real — Manifest V2 extensions are being phased out across Chrome. We ship Chrome extensions for two of our products (Streetify and an internal client tool) so the change is not academic. Here's what the transition actually looks like.

The headline changes

ConcernManifest V2Manifest V3
Background contextPersistent background pagesService workers (event-driven, terminate when idle)
Network interceptionwebRequest blocking APIdeclarativeNetRequest (rule-based, no JS)
Remote codeAllowed (eval, dynamic imports)Blocked
PermissionsAll-or-nothing on installGranular host permissions, per-site grants
Update urgencyActive until phase-outNew extensions require V3 since 2022
Manifest V2 vs V3 — the surface changes.

Why Google says it matters

  • 01Security — fewer extensions can quietly intercept every request you make.
  • 02Performance — service workers consume less memory than persistent background pages.
  • 03Privacy — content scripts no longer get blanket access to everything you visit.
  • 04Reviewability — declarative rules are easier for Google to inspect than arbitrary blocking code.

Why developers are unhappy

  • 01Ad blockers and privacy tools were built on webRequest's blocking power. Declarative rules are less expressive — uBlock Origin's full ruleset doesn't translate cleanly.
  • 02Service workers terminate aggressively. State management becomes an event-sourcing exercise.
  • 03Debugging extension service workers is harder than debugging persistent backgrounds.
  • 04Many V2 patterns have no clean V3 equivalent — they need redesign, not refactor.

A service-worker background, in code

background.js (Manifest V3)javascript
// V3: no persistent background. The worker wakes for events and exits when idle.
chrome.runtime.onInstalled.addListener(() => {
  chrome.alarms.create('hourly-sync', { periodInMinutes: 60 })
})

chrome.alarms.onAlarm.addListener(async (alarm) => {
  if (alarm.name !== 'hourly-sync') return
  const data = await fetch('https://api.example.com/sync').then(r => r.json())
  // chrome.storage.local persists between worker lifetimes
  await chrome.storage.local.set({ lastSync: Date.now(), data })
})

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.type === 'get-data') {
    chrome.storage.local.get('data').then(({ data }) => sendResponse(data))
    return true   // keep the channel open for async response
  }
})

Manifest V3 is a real tightening of the extension platform — better for users on the whole, worse for the most powerful kind of extensions that existed under V2.

What we did to migrate

  • 01Rewrote the background page as a service worker, treating it as 'a thing that wakes up and goes back to sleep' rather than 'a long-running process'.
  • 02Moved all in-memory state to chrome.storage.session. Anything in-memory disappears the moment the worker terminates.
  • 03Replaced webRequest blocking with declarativeNetRequest rule sets. Generated the rules from the same source-of-truth we used before.
  • 04Audited every permission for whether the user actually needs to grant it upfront, or can grant on demand.

Where it still hurts

  • 01Realtime extensions (timers, polling, anything continuous) are awkward — chrome.alarms with a 30-second minimum is the workaround.
  • 02Anything that needs to inject content into pages dynamically based on remote configuration. The execution model is restrictive.
  • 03Firefox supports a more permissive V3 dialect. We now ship two builds where we used to ship one.

Where to start if you have a V2 extension still

  • 01Read the migration guide end-to-end. It is mostly accurate and saves you a week of trial and error.
  • 02Convert background to service worker first — this is the highest-friction part.
  • 03Replace webRequest blocking with declarativeNetRequest. Use the rule converter Google ships.
  • 04Test on Edge and Brave too. Both follow Chrome but each has its own enforcement schedule.

Manifest V3 is here to stay. It's a real tightening of the extension platform — better for users on the whole, worse for the most powerful kind of extensions that existed under V2. If you ship Chrome extensions, the migration is now urgent.

Talk to Remiam about a system like this.