---
title: "How do you handle schema migrations in IndexedDB (e.g., adding a new field or object store)?"  
description: "How do you handle schema migrations in IndexedDB (e.g., adding a new field or object store)?"  
author: "ICSM Computer"  
published: 2025-07-06  
updated: 2025-07-06  
canonical: https://www.mindstick.com/interview/34320/how-do-you-handle-schema-migrations-in-indexeddb-e-g-adding-a-new-field-or-object-store  
category: "database"  
tags: ["database", "indexeddb"]  
reading_time: 5 minutes  

---

# How do you handle schema migrations in IndexedDB (e.g., adding a new field or object store)?

Schema migrations in [**IndexedDB**](https://www.mindstick.com/interview/34291/how-does-indexeddb-work) 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?

```javascript
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

```javascript
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:

```javascript
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 |

```javascript
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.

## Answers

### Answer by ICSM Computer

Schema migrations in [**IndexedDB**](https://www.mindstick.com/interview/34291/how-does-indexeddb-work) 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?

```javascript
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

```javascript
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:

```javascript
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 |

```javascript
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.


---

Original Source: https://www.mindstick.com/interview/34320/how-do-you-handle-schema-migrations-in-indexeddb-e-g-adding-a-new-field-or-object-store

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
