Schema migrations in IndexedDB are handled using the onupgradeneeded event, which is triggered
only when the database version number increases.
This is how you can safely update the schema (e.g., add a new field, index, or object store)
without losing existing data.
What Triggers a Migration?
const request = indexedDB.open("MyDatabase", 2); // Bump version from 1 → 2
When the version number changes:
The onupgradeneeded event fires.
You have full access to modify the schema: create/delete stores, add indexes, etc.
Example: Add New Object Store & Index
Upgrade from version 1 → 2
const request = indexedDB.open("MyDatabase", 2);
request.onupgradeneeded = function (event) {
const db = event.target.result;
const oldVersion = event.oldVersion;
// Add new store if upgrading to version 2
if (oldVersion < 2) {
const logStore = db.createObjectStore("logs", { keyPath: "id" });
logStore.createIndex("timestamp", "timestamp");
}
// Example: Add a new index to an existing store
if (oldVersion < 3) {
const noteStore = event.target.transaction.objectStore("notes");
noteStore.createIndex("updatedAt", "updatedAt");
}
};
Important: Existing Data Is Preserved
IndexedDB doesn't delete any data by default during upgrades.
If you change a keyPath or structure, you may need to:
Read old data
Create a new store
Migrate data manually
Delete old store
Example: Manual Data Migration
Suppose you need to convert an old store to a new structure:
if (oldVersion < 4) {
const oldStore = db.objectStoreNames.contains("notes") && db.deleteObjectStore("notes");
const newStore = db.createObjectStore("notes", { keyPath: "id" });
newStore.createIndex("title", "title");
newStore.createIndex("userId", "userId");
// You could read from old store before deleting it and write to new one
}
Avoid Common Mistakes
Mistake
Fix
Forgetting to bump the version
Must increase version number
Calling createObjectStore() twice
Always check if it already exists
Changing keyPath on existing store
Delete and recreate store to change it
Not handling onblocked event
Inform user to close other tabs
request.onblocked = function () {
alert("Please close other tabs to complete the database upgrade.");
};
Best Practices for Migrations
Tip
Why
Use version guards (if (oldVersion < X))
Allows multi-step upgrades from any version
Preserve existing data during migration
Avoids data loss
Test upgrades from older versions
Ensure backward compatibility
Use onblocked and onerror
Ensure upgrade isn't silently blocked
Summary
Schema changes are made in onupgradeneeded.
You must increment the version to trigger it.
Safely add/remove stores, indexes, or migrate structure inside this event.
Always handle onblocked, onerror, and version checks.
Markdown for AI
A clean, structured version of this page for AI assistants and LLMs.
We use cookies to ensure you have the best browsing experience on our website. By using our site, you
acknowledge that you have read and understood our
Cookie Policy &
Privacy Policy.
Schema migrations in IndexedDB are handled using the
onupgradeneededevent, which is triggered only when the database version number increases.This is how you can safely update the schema (e.g., add a new field, index, or object store) without losing existing data.
What Triggers a Migration?
When the version number changes:
onupgradeneededevent fires.Example: Add New Object Store & Index
Upgrade from version 1 → 2
Important: Existing Data Is Preserved
IndexedDB doesn't delete any data by default during upgrades.
If you change a keyPath or structure, you may need to:
Example: Manual Data Migration
Suppose you need to convert an old store to a new structure:
Avoid Common Mistakes
createObjectStore()twiceonblockedeventBest Practices for Migrations
if (oldVersion < X))onblockedandonerrorSummary
onupgradeneeded.onblocked,onerror, and version checks.