How do you add a new index to an existing IndexedDB store?

Tests production schema migration discipline. Bump the integer version in open(), handle onupgradeneeded before onsuccess, use event.oldVersion for incremental changes, and guard against duplicate index creation.
What's really being asked
Your grasp of IndexedDB's strictly versioned schema model and your ability to manage zero-downtime client-side migrations in production. Interviewers want to see that you know schema mutations are gated behind version changes, not arbitrary transactions, and that you can reason about idempotency, incremental upgrades, and concurrent tab behavior.
The full answer
First, bump the integer version passed to indexedDB.open. The browser detects a higher version and fires onupgradeneeded before onsuccess. Second, inside the onupgradeneeded handler, inspect event.oldVersion to decide which migrations to run. If oldVersion is less than your target, conditionally create the new index with objectStore.createIndex. Third, guard against re-running the same migration by checking if the index already exists or by branching strictly on oldVersion ranges. Fourth, register an onblocked handler because existing connections in other tabs will delay the upgrade until they close. Fifth, note that version numbers are integers subject to rounding, so only use whole numbers.
The mistakes people make
Attempting to call createIndex during a normal readwrite transaction outside onupgradeneeded. Failing to increment the version number and expecting the schema to change. Writing an upgrade handler that ignores event.oldVersion and blindly recreates object stores or indexes, which throws errors if they already exist. Forgetting that onupgradeneeded runs in its own transaction, meaning you do not manually create one for schema changes.
What usually comes next
How would you handle a user with ten tabs open during the upgrade? What if you need to backfill data into the new index? How do you delete a deprecated index or object store? What happens if you need to downgrade the schema?
A concrete example
Suppose the database is at version 2. You call indexedDB.open("AppDB", 3). The browser queues an upgrade. In the onupgradeneeded handler, you read const db = event.target.result. If event.oldVersion < 3, you get the object store via const store = event.target.transaction.objectStore("users"), then call store.createIndex("email_idx", "email", { unique: false }). You do not create a new transaction. After the handler finishes, onsuccess fires and the app resumes normal operations. If another tab holds a connection to version 2, onblocked fires until that tab closes or reloads.
Interview question
Which approach correctly adds an index to an existing IndexedDB store while preserving data and handling production constraints?
- a.Increment the version in indexedDB.open, then in onupgradeneeded delete the object store and recreate it with the new index to ensure a clean schema.
- b.Open the database at the current version, begin a readwrite transaction, and call objectStore.createIndex inside the transaction.
- c.Increment the version in indexedDB.open, conditionally create the index inside onupgradeneeded based on event.oldVersion, and attach an onblocked handler for other tabs.Correct
- d.Increment the version in indexedDB.open, then in onsuccess check if the index exists and create it with a manually started transaction if missing.
Why? this is the answer
IndexedDB schema mutations require a version bump and must run inside onupgradeneeded, where event.oldVersion enables incremental idempotent migrations and onblocked handles concurrent tabs. Option B is wrong because createIndex is not allowed in a normal readwrite transaction outside the upgrade handler.
Just read this? Test yourself on what you have been reading.
Read the original → developer.mozilla.org
- #indexeddb
- #web-apis
- #schema-migration
- #typescript
- #browser-storage
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.
See open roles