Using browser.storage.sync vs storage.local in Firefox Extensions: When to Use Each
Firefox extensions have two main storage options: browser.storage.sync and browser.storage.local. Picking the wrong one leads to frustrating UX. Here's how to think about it.
The Core Difference
storage.sync |
storage.local |
|
|---|---|---|
| Synced across devices | Yes (via Firefox Sync) | No |
| Quota | 100KB (8KB per item) | 10MB |
| Requires Firefox Sync | Yes, to actually sync | No |
| Falls back gracefully | Yes (local if not synced) | N/A |
storage.sync: User Preferences
Use sync for anything that should feel the same across all the user's Firefox installations:
// Settings that should follow the user
await browser.storage.sync.set({
temperatureUnit: 'celsius', // °C or °F
timeFormat: '24h', // 12h or 24h
theme: 'dark', // dark or light
defaultLocation: 'London', // weather location
worldClocks: [ // configured clocks
{ timezone: 'America/New_York', label: 'New York' },
{ timezone: 'Asia/Tokyo', label: 'Tokyo' },
]
});
If a user sets their preferred city on their laptop, it should appear on their desktop too.
storage.local: Cached Data
Use local for ephemeral data — API responses, cache, large blobs:
// Cache fetched weather data (don't sync — it's ephemeral)
await browser.storage.local.set({
weatherCache: {
London: {
data: { temp: 15, description: 'Cloudy' },
timestamp: Date.now()
}
}
});
Caching weather data in sync would hit quota limits fast and waste sync bandwidth on data that expires in 10 minutes.
Quota Handling
storage.sync has strict limits:
- Total: ~100KB
- Per item: 8KB
- Number of items: 512
Always handle quota errors gracefully:
async function saveUserPreferences(prefs) {
try {
await browser.storage.sync.set(prefs);
} catch (error) {
if (error.message.includes('QUOTA_BYTES')) {
console.warn('Sync storage quota exceeded, falling back to local');
await browser.storage.local.set(prefs);
} else {
throw error;
}
}
}
Reading with Defaults
Always provide defaults when reading — the storage might be empty on first install:
const DEFAULTS = {
temperatureUnit: 'celsius',
timeFormat: '24h',
theme: 'auto',
defaultLocation: '',
worldClocks: [],
};
async function loadPreferences() {
const stored = await browser.storage.sync.get(DEFAULTS);
// stored will contain stored values OR defaults for missing keys
return stored;
}
Listening for Cross-Device Changes
When sync is active, settings can change from another device:
browser.storage.onChanged.addListener((changes, area) => {
if (area !== 'sync') return;
if (changes.theme) {
applyTheme(changes.theme.newValue);
}
if (changes.temperatureUnit) {
refreshWeatherDisplay();
}
if (changes.worldClocks) {
rebuildClockList(changes.worldClocks.newValue);
}
});
This is what makes sync powerful — changes propagate to all open tabs/windows automatically.
The Pattern I Use
In Weather & Clock Dashboard, the storage strategy is:
const SYNC_KEYS = ['theme', 'temperatureUnit', 'timeFormat', 'defaultLocation', 'worldClocks'];
const LOCAL_KEYS = ['weatherCache', 'lastUpdated'];
// On startup: load sync prefs, use local cache
async function init() {
const prefs = await browser.storage.sync.get(DEFAULTS);
applyPreferences(prefs);
// Try to load cached weather first (instant)
const { weatherCache } = await browser.storage.local.get('weatherCache');
if (weatherCache && isFresh(weatherCache)) {
displayWeather(weatherCache.data);
}
// Then refresh in background
fetchAndCacheWeather(prefs.defaultLocation);
}
This gives instant load from cache, with the user's synced location preference, and fresh data arriving silently.
Common Mistakes
-
Caching API responses in
storage.sync— Wastes quota and sync bandwidth - Not providing defaults — Silent failures on first install
-
Not listening for
storage.onChanged— UI won't update when sync kicks in -
Storing large blobs in
sync— Base64 images, etc. will exceed the 8KB per-item limit
When Firefox Sync is Disabled
storage.sync falls back gracefully — it still works, just locally. You don't need to check whether Firefox Sync is enabled. The extension works the same on a single device; it just won't sync.
Weather & Clock Dashboard — free Firefox new tab extension with live weather, world clocks, search bar. No tracking, MIT licensed.
Top comments (0)