Chrome Extension Alarms & Scheduling — Developer Guide
5 min readBackground Scheduling with chrome.alarms
Introduction
chrome.alarmsis THE way to schedule background tasks in MV3- Replaces
setInterval/setTimeoutwhich don’t survive service worker termination - Requires
"alarms"permission - Cross-ref:
docs/permissions/alarms.md
manifest.json
{
"permissions": ["alarms"],
"background": { "service_worker": "background.js" }
}
Creating Alarms
One-Time Alarm
chrome.alarms.create("checkUpdates", {
delayInMinutes: 5 // Fire once, 5 minutes from now
});
Repeating Alarm
chrome.alarms.create("syncData", {
delayInMinutes: 1, // First fire after 1 minute
periodInMinutes: 30 // Then every 30 minutes
});
Alarm at Specific Time
chrome.alarms.create("dailyReport", {
when: new Date("2024-01-15T09:00:00").getTime() // Unix timestamp
});
Handling Alarms
chrome.alarms.onAlarm.addListener((alarm) => {
switch (alarm.name) {
case "checkUpdates":
checkForUpdates();
break;
case "syncData":
syncDataToServer();
break;
case "dailyReport":
generateReport();
break;
}
});
- Register listener at TOP LEVEL of service worker (not inside async functions)
- Handler wakes up the service worker if it was terminated
Managing Alarms
Get Alarm Info
chrome.alarms.get("syncData", (alarm) => {
if (alarm) {
console.log("Next fire:", new Date(alarm.scheduledTime));
console.log("Period:", alarm.periodInMinutes, "minutes");
}
});
List All Alarms
chrome.alarms.getAll((alarms) => {
alarms.forEach(a => console.log(a.name, new Date(a.scheduledTime)));
});
Cancel Alarms
chrome.alarms.clear("syncData"); // Cancel specific alarm
chrome.alarms.clearAll(); // Cancel all alarms
MV3 Minimum Interval
- Minimum period: 30 seconds in production (was 1 minute, reduced in Chrome 120+)
- In development (unpacked): can be shorter
- For sub-30-second tasks, use
chrome.alarmsas a wake-up and then usesetTimeoutwithin the handler
Common Patterns
Periodic Data Sync
// Setup on install
chrome.runtime.onInstalled.addListener(() => {
chrome.alarms.create("sync", { periodInMinutes: 60 });
});
// Handle sync
chrome.alarms.onAlarm.addListener(async (alarm) => {
if (alarm.name === "sync") {
const data = await fetchFromServer();
const storage = createStorage(defineSchema({ lastSync: 'number', data: 'string' }), 'local');
await storage.setMany({ lastSync: Date.now(), data: JSON.stringify(data) });
}
});
Badge Update (Unread Count)
chrome.alarms.create("updateBadge", { periodInMinutes: 5 });
chrome.alarms.onAlarm.addListener(async (alarm) => {
if (alarm.name === "updateBadge") {
const count = await getUnreadCount();
chrome.action.setBadgeText({ text: count > 0 ? String(count) : "" });
}
});
Reminder System
- User sets reminders via popup
- Store reminder times with
@theluckystrike/webext-storage - Create alarm for each reminder
- Show
chrome.notificationswhen alarm fires
Session Cleanup
- Periodic cleanup of stale data in storage
clearAll()on extension update, recreate needed alarms
Alarms + Storage Integration
import { createStorage, defineSchema } from '@theluckystrike/webext-storage';
const storage = createStorage(defineSchema({
syncInterval: 'number',
lastSync: 'number'
}), 'sync');
// User changes sync interval in options
async function updateSyncInterval(minutes) {
await storage.set('syncInterval', minutes);
await chrome.alarms.clear("sync");
chrome.alarms.create("sync", { periodInMinutes: minutes });
}
Best Practices
- Create alarms in
chrome.runtime.onInstalled— they persist across restarts - Use descriptive alarm names — easier to debug
- Always register
onAlarmat top level of service worker - Don’t create duplicate alarms — check with
get()first or just overwrite - Handle the case where alarm fires while offline (for network tasks)
- Log alarm activity for debugging
Common Mistakes
- Using
setTimeout/setInterval— doesn’t survive SW termination - Registering
onAlarminside an async function — listener won’t catch events - Setting period less than 30 seconds — silently clamped to minimum
- Not handling extension update — alarms persist but handlers may change
- Creating alarm with same name overwrites previous — can be feature or bug
Related Articles
Related Articles
Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.
Turn Your Extension Into a Business
Ready to monetize? The Extension Monetization Playbook covers freemium models, Stripe integration, subscription architecture, and growth strategies for Chrome extension developers.