How to Integrate FlexSearch with IndexedDB for Persistent Browser Storage
You can integrate FlexSearch with IndexedDB by instantiating the IndexedDB storage adapter and mounting it to your FlexSearch Index or Document using await index.mount(db), which persists the inverted index across browser sessions in five dedicated object stores.
The nextapps-de/flexsearch library provides a high-performance full-text search engine that runs entirely in the browser. When you integrate FlexSearch with IndexedDB, you create durable search indexes that survive page reloads without re-indexing your entire dataset.
How the FlexSearch IndexedDB Adapter Works
The integration relies on the IdxDB class located in src/db/indexeddb/index.js. This adapter implements the generic StorageInterface used by all persistent backends in FlexSearch (including SQLite and Redis).
When mounted, the adapter creates five object stores within your IndexedDB database to store different index components:
map– term to document ID mappingsctx– context term mappingstag– tag-based indicesreg– raw document cache (optional)cfg– index configuration snapshot
Each store name is suffixed with the field name (e.g., map:content), allowing multiple FlexSearch indexes to share the same IndexedDB database without collisions.
Step-by-Step Integration Guide
1. Create the FlexSearch Index
Instantiate a standard FlexSearch Index or Document. The constructor accepts the same encoding, tokenization, and caching options you would use for an in-memory index.
import { Index } from "flexsearch";
const index = new Index({
encode: "icase",
tokenize: "forward",
cache: true
});
2. Initialize the IndexedDB Adapter
Create an IndexedDB instance with a unique namespace. This namespace becomes the store name prefix in IndexedDB.
import { IndexedDB } from "flexsearch";
const db = new IndexedDB("my-search-index");
3. Mount the Storage
Register the adapter with your index. The mount method opens the IndexedDB connection, creates object stores if they do not exist, and prepares the index for persistence.
await index.mount(db);
4. Index Documents
Add documents as usual. Changes are buffered in memory until the commit cycle runs.
index.add(1, "FlexSearch provides fast full-text search");
index.add(2, "IndexedDB persists data across browser sessions");
5. Commit Changes
By default, FlexSearch auto-commits after a short delay. For deterministic persistence, explicitly await the commit.
await index.commit();
Complete Working Example
This ES module example demonstrates the full lifecycle including recovery after a simulated page reload.
import { Index, IndexedDB } from "https://cdn.jsdelivr.net/npm/flexsearch@latest/dist/flexsearch.bundle.module.min.js";
// Create index and storage adapter
const index = new Index({ tokenize: "forward" });
const db = new IndexedDB("tutorial-store");
// Mount existing or create new IndexedDB
await index.mount(db);
// Add data if this is a fresh index
if (!index.search("flex").length) {
index.add(1, "FlexSearch integrates seamlessly with IndexedDB");
index.add(2, "Persistent storage survives browser refreshes");
await index.commit();
}
// Search immediately works
console.log(index.search("persistent")); // → [2]
// Simulate recovery after page reload
const index2 = new Index();
await index2.mount(db);
console.log(index2.search("flex")); // → [1]
Managing the Persistence Lifecycle
Auto-Commit vs. Manual Commit
FlexSearch defaults to auto-commit mode, where add, update, and remove operations trigger an asynchronous write after a brief delay. For batch operations or transaction-like control, disable auto-commit and manage writes manually.
const index = new Index({ commit: false });
await index.mount(db);
// Bulk index without intermediate writes
for (let i = 0; i < 1000; i++) {
index.add(i, `record content ${i}`);
}
// Single atomic commit
await index.commit();
Clearing and Destroying Data
To remove data without deleting the database structure, use clear(). To completely remove the IndexedDB database, use destroy().
// Empty all object stores for this namespace
await index.clear();
// Permanently delete the IndexedDB database
await index.destroy();
Working with Document Indexes
The Document class, which supports multi-field search, uses the same mounting pattern. Each field receives its own suffixed object stores (e.g., map:title, map:content), preventing collisions when multiple fields share one IndexedDB database.
import { Document, IndexedDB } from "flexsearch";
const db = new IndexedDB("blog-index");
const doc = new Document({
document: {
id: "id",
title: { tag: "title" },
content: { tag: "content" }
}
});
await doc.mount(db);
doc.add({ id: 1, title: "FlexSearch Guide", content: "How to use IndexedDB" });
await doc.commit();
Summary
- Mount the adapter: Create an
IndexedDBinstance with a namespace and callawait index.mount(db)to connect FlexSearch to the browser's IndexedDB. - Understand the storage model: The adapter creates five object stores (
map,ctx,tag,reg,cfg) per field to store term mappings and configuration. - Control persistence: Auto-commit handles writes automatically, but you can disable it with
{ commit: false }and useawait index.commit()for deterministic batch operations. - Manage lifecycle: Use
await index.clear()to empty stores orawait index.destroy()to delete the entire IndexedDB database. - Support Documents: The same pattern works for multi-field
Documentindexes, with each field receiving isolated object stores via suffixes.
Frequently Asked Questions
Does FlexSearch automatically load existing data from IndexedDB when I call mount()?
Yes. When you call await index.mount(db), the IdxDB.prototype.open method in src/db/indexeddb/index.js opens the database connection and creates the object stores if they do not exist. While the index data is not fully loaded into memory immediately, the stores are accessible, and FlexSearch reads from them as needed when searches are performed or when the index is rebuilt.
Can I use multiple FlexSearch indexes with the same IndexedDB database?
Yes. The IndexedDB adapter uses a namespace system where each index (and each field in a Document index) receives suffixed object store names. For example, a field named "content" creates stores named map:content, ctx:content, etc. This design allows you to instantiate multiple IndexedDB adapters with different namespaces or share one database across multiple Index instances without data collisions.
What happens if I don't call commit() when using FlexSearch with IndexedDB?
By default, FlexSearch operates in auto-commit mode, meaning it automatically schedules a commit after every mutating operation (add, update, remove). If you disable auto-commit by passing { commit: false } to the Index constructor and then fail to call await index.commit(), your changes remain in memory only and are never written to IndexedDB. This results in data loss when the page reloads.
How do I completely remove a FlexSearch index from IndexedDB?
To permanently delete the IndexedDB database associated with your FlexSearch index, call await index.destroy(). This method, implemented in IdxDB.prototype.destroy at src/db/indexeddb/index.js, drops the entire database file from the browser using the IndexedDB deleteDatabase API. Alternatively, use await index.clear() to empty the object stores while preserving the database structure for reuse.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →