April 29, 2026 · 8 min read

Debugging IndexedDB in Chrome DevTools — the practical guide

How to inspect, query, and edit IndexedDB from Chrome DevTools — the workflow built into the Application panel, the bits that miss the mark, and what to do about it.

Why IndexedDB debugging gets painful

IndexedDB started as the “serious” client-side database API after WebSQL was deprecated. It’s asynchronous, transactional, supports indexes, and survives page reloads — exactly the storage backbone a local-first or offline-capable app needs. What it isn’t is friendly to inspect at scale.

The Chrome DevTools Application panel exposes the raw structure: databases, object stores, indexes, and a paginated table of records. That’s enough to confirm a key/value pair landed where you expected. It is not enough for the question “why does this object store have 18,000 rows when we only sync 8,000 events?”

The core workflow inside the Application panel

Here’s the bare-minimum path that ships with Chrome:

  1. Open DevTools → Application tab → expand Storage → IndexedDB.
  2. Pick a database, then an object store. Records load into the right pane. Click any cell to expand its value tree.
  3. Click Refresh (the circular arrow in the top left) any time the running page mutates the store — the panel does not auto-poll.
  4. Use the Delete selected button to remove a row, or right-click → Delete database to nuke the whole thing during local dev.

That covers the inspect-and-clear workflow. What it doesn’t cover is filtering, querying, exporting, or understanding what fields actually exist on a row.

Five things the built-in panel doesn't do

1. Filter records

There’s a Start from keyinput that scrolls the cursor to a primary key, but no “show me only the rows where status === "refunded".” If your store is meaningful, you’re scrolling.

2. Project columns

Each row renders as a JSON tree. Comparing the same field across many rows means clicking through them one at a time. There’s no tabular projection like “just show me {id, status, total}across these 200 rows.”

3. Round-trip non-JSON types

IndexedDB stores arbitrary structured-clone values: Date, Map, Set, BigInt, ArrayBuffer, Blob, even circular references. Copying out of the panel stringifies most of these — by the time they hit your clipboard they’re lossy.

4. Bulk-edit

You can edit a top-level cell value in some panel modes, but nested fields and bulk operations require code in the page’s console.

5. See what a store actually contains

The panel never tells you “these 1,200 rows have these 14 fields, with these types, and shippingCityis missing on 38% of them.” That’s a schema-inference problem, and it’s where most non-trivial IndexedDB debugging actually starts.

The console fallback (and why it doesn't scale)

When the panel runs out of road, most people drop into the console:

const open = indexedDB.open("local_first_app");
open.onsuccess = () => {
  const db = open.result;
  const tx = db.transaction("orders", "readonly");
  const store = tx.objectStore("orders");
  const req = store.openCursor();
  const out = [];
  req.onsuccess = (e) => {
    const cur = e.target.result;
    if (!cur) { console.table(out); return; }
    if (cur.value.status === "refunded") out.push(cur.value);
    cur.continue();
  };
};

Three problems with this:

  • You re-type it every time. There’s no history, no shareable artifact.
  • console.table truncates nested fields and gives you no way to round-trip the result back into the database or out to CSV.
  • You’re bypassing the IDB index machinery entirely — the cursor scans every row even when an index would have answered the query in O(log n + k).

What to do instead

The shape of the problem is well-known: IndexedDB needs a real query interface, schema inference, projection, sort/limit, and bulk-export. That’s exactly the gap IdxBeaver fills inside DevTools — it gives you a MongoDB-style filter language, an index-aware planner, an inferred schema view, multi-tab queries, and exports across JSON, NDJSON, CSV, SQL, and ZIP. Same data, same browser, same DevTools panel — just with the operators a real database client gives you.

If you’re curious how the query language compiles down, the companion post on MongoDB-style filters over IndexedDB walks through the planner.


← All posts