Offline Storage

PWA storage has two jobs: cache resources so the app opens, and store user data so work is not lost.

Storage Choices

StorageUse forAvoid for
Cache StorageHTML, JS, CSS, images, fonts, offline fallback pages, safe API responsesStructured records, drafts, business data
IndexedDBRecords, blobs, upload queues, sync metadata, migrationsSimple one-off preferences if Web Storage is enough
Web StorageTiny preferencesLarge data, async flows, sensitive records, offline databases
Storage ManagerQuota, usage, persistence requestsBusiness logic storage itself

IndexedDB Shape

const request = indexedDB.open('ledger', 1);

request.onupgradeneeded = () => {
  const db = request.result;
  db.createObjectStore('entries', { keyPath: 'id' });
  db.createObjectStore('outbox', { keyPath: 'id' });
};

request.onsuccess = () => {
  const db = request.result;
  const tx = db.transaction('entries', 'readwrite');
  tx.objectStore('entries').put({
    id: crypto.randomUUID(),
    amount: 1200,
    synced: false,
  });
};

Eviction Reality

Browsers manage storage under origin quota. Users can clear data. Private browsing can behave differently. Persistent storage can reduce eviction risk, but it is not a backup.

if ('storage' in navigator && 'persist' in navigator.storage) {
  const persisted = await navigator.storage.persist();
  console.log(`Persistent storage granted: ${persisted}`);
}

Gotcha: Offline-first apps need export or backup. IndexedDB persistence is not a disaster recovery plan.