Your setTimeout Didn't Break — Chrome Killed It
The log said the sync was scheduled. Two minutes later, nothing had run. No error, no rejected promise, no missed callback warning — just a line that promised future work and a database that never changed. Here is the excerpt that ended a week of blaming my own debounce logic: [10:41:02] change detected [10:41:02] sync scheduled in 120000ms [10:41:32] service worker terminated (idle) The timer…
Chrome's MV3 killed the setTimeout that was not broken. A log showed a sync scheduled, but no action took place after two minutes. The worker was terminated without any error or warning. The issue came from JavaScript semantics, not the debounce logic or code coalescing. Chrome keeps a background service worker alive as long as it handles events, but idle timers do not count as activity.
A timer longer than the idle window is unpredictable, surviving only if the worker is woken up. Fix 1 is to store the deadline and arm an alarm, fixing most features. Fix 2 is to run the delay where the user is active, like in a content script. Fix 3 is to keep the worker active with a message every 20 seconds, though it burns battery and annoys reviewers.
Fix 4 is to move the timer plumbing into the build using tools like vite-mv3-sw-compile-persist, which rewrites long timeouts into alarm-backed wrappers at build time.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.