Background Scheduling with chrome.alarms

Introduction {#introduction}

manifest.json {#manifestjson}

{
  "permissions": ["alarms"],
  "background": { "service_worker": "background.js" }
}

Creating Alarms {#creating-alarms}

One-Time Alarm {#one-time-alarm}

chrome.alarms.create("checkUpdates", {
  delayInMinutes: 5  // Fire once, 5 minutes from now
});

Repeating Alarm {#repeating-alarm}

chrome.alarms.create("syncData", {
  delayInMinutes: 1,     // First fire after 1 minute
  periodInMinutes: 30    // Then every 30 minutes
});

Alarm at Specific Time {#alarm-at-specific-time}

chrome.alarms.create("dailyReport", {
  when: new Date("2024-01-15T09:00:00").getTime()  // Unix timestamp
});

Handling Alarms {#handling-alarms}

chrome.alarms.onAlarm.addListener((alarm) => {
  switch (alarm.name) {
    case "checkUpdates":
      checkForUpdates();
      break;
    case "syncData":
      syncDataToServer();
      break;
    case "dailyReport":
      generateReport();
      break;
  }
});

Managing Alarms {#managing-alarms}

Get Alarm Info {#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 {#list-all-alarms}

chrome.alarms.getAll((alarms) => {
  alarms.forEach(a => console.log(a.name, new Date(a.scheduledTime)));
});

Cancel Alarms {#cancel-alarms}

chrome.alarms.clear("syncData");    // Cancel specific alarm
chrome.alarms.clearAll();            // Cancel all alarms

MV3 Minimum Interval {#mv3-minimum-interval}

Common Patterns {#common-patterns}

Periodic Data Sync {#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) {#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 {#reminder-system}

Session Cleanup {#session-cleanup}

Alarms + Storage Integration {#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 {#best-practices}

Common Mistakes {#common-mistakes}

Related Articles {#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.