Skip to content

Add support for IndexedDB#939

Open
aknolan wants to merge 4 commits into
mainfrom
user/aknolan/add-indexeddb
Open

Add support for IndexedDB#939
aknolan wants to merge 4 commits into
mainfrom
user/aknolan/add-indexeddb

Conversation

@aknolan

@aknolan aknolan commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Adds support for IndexedDB under persist-structured-data with guide, expectations, and demo.

@aknolan aknolan enabled auto-merge (squash) June 10, 2026 21:04
- **DO** use `put()` when you want insert-or-update semantics. Use `add()` only when you want an error if the key already exists.
- **DO** use indexes and key ranges (`IDBKeyRange`) for efficient queries instead of iterating all records with a cursor.
- **DO** use `"readonly"` transactions for reads. Multiple readonly transactions can run concurrently, but only one `"readwrite"` transaction per object store is active at a time.
- **DO NOT** store sensitive data (tokens, passwords, PII) in IndexedDB without encryption. IndexedDB is not a secure store — any script running on the origin can access it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it'd be worth having a separate guide on how to use encryption to secure sensitive data in IDB?

Comment thread guides/user-experience/persist-structured-data/guide.md Outdated
name: persist-structured-data
description: Store and retrieve structured application data client-side using IndexedDB, enabling offline access, fast local reads, and reduced network dependency without relying on cookies or localStorage for complex data.
web-feature-ids:
- indexeddb

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also the related web feature getAllRecords(). It's "Limited availability" but is there anything more we want to say about it in this guide?

}
```

### Storage quota

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like good general advice to include in the main body of the guide, outside of the fallback strategy section. (It doesn't depend on browser support)

Could you move this up to its own H2 section?

const notes = await getAllNotes(db);
```

## Best Practices

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either in its own section, or one of the bullets in this section, we should also include the best practices for back/forward cache eligibility:

  • Closing open IndexedDB connections during the pagehide event
  • Reopening or reconnecting to them during the pageshow event

https://web.dev/articles/bfcache#close-open-connections

The example code, demo.html, and expectations.md should also be updated to reflect it.

cc @tunetheweb @gilbertococchi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this Rick, +1, it would be more than ideal to guide developers towards this approach to avoid unexpected bfcache ineligibility scenarios.

Comment thread guides/user-experience/persist-structured-data/guide.md Outdated

```javascript
const DB_NAME = "app-notes";
const DB_VERSION = 1;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any best practices on when to change the version number that would be worth including?

const record = { ...note, updatedAt: Date.now() };
const request = store.add(record);

request.onsuccess = () => resolve(request.result);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be oncomplete?

IIUC in some situations the success event can be fired before the transaction is aborted or actually written to disk.

const request = store.add(record);

request.onsuccess = () => resolve(request.result);
tx.onerror = () => reject(tx.error);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also need to handle tx.onabort in addition to errors?

@rviscomi

Copy link
Copy Markdown
Member

Seeing as how IndexedDB is already a Widely available web feature, I also used the MWG Demo app to assess how well an unguided coding agent would adhere to these best practices.

image

The unguided agent reached for localStorage when it shouldn't have, so it failed most expectations. The guided agent correctly used IndexedDB and passed all of the expectations. Without the bfcache eligibility or onabort best practices, the guided agent didn't automatically support them, reaffirming that they're needed.

aknolan and others added 2 commits June 30, 2026 14:48
Remove redundant widely available message and reframe fallback verbiage

Co-authored-by: Rick Viscomi <rviscomi@users.noreply.github.com>
Take suggestion that metadata is no longer needed

Co-authored-by: Rick Viscomi <rviscomi@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants