Chrome Extension Alarms & Scheduling — Developer Guide

5 min read

Background Scheduling with chrome.alarms

Introduction

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;
  }
});

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

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

Session Cleanup

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

Common Mistakes

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.