Storage

Persist settings and runtime state with browser storage APIs that match the extension context you are building.

Extension.js does not replace browser storage APIs. It helps you compile the code that uses them, but storage decisions still affect service-worker reliability, cross-browser behavior, sync expectations, and migration safety.

Choose the right storage area

Storage areaUse whenNotes
storage.localdurable extension state on one devicebest default for most extension data
storage.syncsmall user preferences across signed-in browsersquota-sensitive and slower than local
storage.sessionshort-lived session stateuseful for ephemeral runtime coordination
storage.managedenterprise-managed policy valuesschema-driven, read-only to the extension
  • Use storage.local for feature state, caches, and durable settings.
  • Use storage.sync only for small, user-meaningful preferences.
  • Use storage.session for state that should not survive a full browser restart.
  • Treat storage.managed as a separate enterprise path, not your general settings mechanism.

Service-worker-friendly patterns

MV3 background service workers can stop and restart between events, so do not rely on in-memory state alone.

  • Rehydrate critical state from storage on demand.
  • Cache in memory only as an optimization.
  • Keep startup work small so event handling stays responsive.
  • Persist versioned settings changes rather than assuming a singleton background runtime.

Example settings module

const SETTINGS_KEY = 'settings'

export async function getSettings() {
  const result = await chrome.storage.local.get(SETTINGS_KEY)
  return result[SETTINGS_KEY] ?? {theme: 'system'}
}

export async function setSettings(nextSettings: {
  theme: 'system' | 'light' | 'dark'
}) {
  await chrome.storage.local.set({[SETTINGS_KEY]: nextSettings})
}

Storage design checklist

  1. Decide which values must survive browser restarts.
  2. Decide which values should sync across devices, if any.
  3. Version your stored data shape before the first release.
  4. Keep a migration path for renamed keys or changed structures.
  5. Avoid storing secrets in client-readable extension storage unless you fully accept that exposure model.

Managed storage

If you use storage.managed, pair the runtime code with a valid storage.managed_schema file in manifest.json. Extension.js validates that schema file as a JSON object and emits it to the canonical output path.

For the JSON resource details, see JSON.

Common mistakes

  • Using storage.sync for large data sets or caches.
  • Assuming background in-memory variables are durable in MV3.
  • Storing multiple disconnected keys without a versioning strategy.
  • Mixing enterprise-managed storage with user-editable settings in the same mental model.
  • Declare schema-backed enterprise storage in manifest.json.
  • Review resource handling in JSON.
  • Move state between contexts with Messaging.