v145 · Web APIs · Storage

IndexedDB: SQLite backend (in-memory contexts)

Chrome 145 ships a SQLite-backed implementation of IndexedDB for in-memory contexts — private browsing, opaque origins, and storage partitions — replacing the legacy LevelDB backend for these cases.

background

Chrome's IndexedDB has historically used LevelDB as its storage backend. A parallel SQLite backend was developed for improved reliability and consistency. Chrome 145 switches in-memory contexts (incognito, opaque origins) to the SQLite backend first, since these contexts hold no persistent data and the migration carries no data-loss risk.

From a web developer perspective, IndexedDB behaviour is unchanged — the switch is internal. This is a stepping stone toward moving all persistent IndexedDB storage to SQLite in a future release.

concepts

  1. IDB Demo

    Creates an IndexedDB database, writes and reads records, and checks storage estimates — works identically whether backed by LevelDB or SQLite, demonstrating the transparent migration.

  2. Memory Context Guide

    What counts as an in-memory context, how storage APIs behave in incognito and opaque origins, and the difference between temporary and persistent storage partitions.

  3. Perf Comparator

    Benchmark bulk insert, point gets, range cursors, and full scans against an in-memory IDB store, and watch the latency curve change shape under the SQLite backend.

  4. Storage Context Probe

    Runs a battery of storage API tests — IndexedDB, quota, persistence, Cache API, localStorage — to characterise the current context. Demonstrates that IndexedDB now works in incognito (SQLite backend in Chrome 145) and explains which incognito detection methods still work and which don't.

the change

// No API change — IndexedDB works identically.
// The backing store (SQLite vs LevelDB) is transparent.

const db = await new Promise((resolve, reject) => {
  const req = indexedDB.open('my-db', 1);
  req.onupgradeneeded = e => {
    e.target.result.createObjectStore('items', { keyPath: 'id' });
  };
  req.onsuccess = e => resolve(e.target.result);
  req.onerror = e => reject(e.target.error);
});

// Write
const tx = db.transaction('items', 'readwrite');
tx.objectStore('items').put({ id: 1, name: 'hello' });

// Read
const tx2 = db.transaction('items', 'readonly');
const req = tx2.objectStore('items').get(1);
req.onsuccess = () => console.log(req.result);

// Works in incognito (now SQLite-backed in Chrome 145),
// in opaque origins (sandboxed iframes), and normal contexts (LevelDB for now).

references