0Pricing
JavaScript Academy · Lesson

Versioning and Upgrades

Migrate schemas with version changes.

Versioning and Upgrades is a free JavaScript Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the JavaScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Versioning?

Apps evolve: you add stores, add indexes, or change how data is shaped. IndexedDB uses a version number to manage these schema changes safely across every user's browser.

The Version Number

The second argument to open is the version, a positive integer. Raising it tells the browser the schema has changed and triggers an upgrade.

// Bumping from 1 to 2 triggers onupgradeneeded:
const request = indexedDB.open('app-db', 2);

Upgrade Only Goes Up

You can only increase the version. Opening with a lower number than the stored one fails with an error. Never decrement.

// If the stored DB is version 3:
const req = indexedDB.open('app-db', 2);
req.onerror = () => console.log('cannot open older version');

oldVersion and newVersion

Inside onupgradeneeded, the event exposes oldVersion and newVersion. Use them to apply only the migrations that haven't run yet.

request.onupgradeneeded = (e) => {
  console.log('upgrading from', e.oldVersion, 'to', e.newVersion);
};

Incremental Migrations

A robust pattern is a fall-through using oldVersion: each block builds on the previous so a user on any old version reaches the latest schema.

request.onupgradeneeded = (e) => {
  const db = e.target.result;
  if (e.oldVersion < 1) {
    db.createObjectStore('notes', { keyPath: 'id' });
  }
  if (e.oldVersion < 2) {
    db.createObjectStore('tags', { keyPath: 'name' });
  }
};

Adding an Index Later

To add an index to an existing store during an upgrade, get the store from the upgrade transaction and call createIndex on it.

request.onupgradeneeded = (e) => {
  if (e.oldVersion < 3) {
    const store = e.target.transaction.objectStore('notes');
    store.createIndex('byDate', 'createdAt');
  }
};

The Version Change Transaction

During onupgradeneeded, the event's transaction is a special versionchange transaction. It is the only context where schema edits and data migration can both happen.

request.onupgradeneeded = (e) => {
  const tx = e.target.transaction; // versionchange tx
  const store = tx.objectStore('notes');
  // migrate existing records here if needed
};

Migrating Existing Data

If a schema change requires reshaping records, iterate the store with a cursor inside the upgrade and put the transformed values back.

const store = e.target.transaction.objectStore('notes');
store.openCursor().onsuccess = (ev) => {
  const cursor = ev.target.result;
  if (cursor) {
    const note = cursor.value;
    note.archived = false; // new field
    cursor.update(note);
    cursor.continue();
  }
};

The versionchange Event

When one tab upgrades, other tabs holding the old version get a versionchange event on their db. They should close so the upgrade is not blocked.

db.onversionchange = () => {
  db.close(); // let the other tab upgrade
  console.log('database is outdated, please reload');
};

Deleting Stores

You can remove an obsolete store during an upgrade with db.deleteObjectStore(name). This permanently drops it and its data.

request.onupgradeneeded = (e) => {
  const db = e.target.result;
  if (e.oldVersion < 4 && db.objectStoreNames.contains('temp')) {
    db.deleteObjectStore('temp');
  }
};

Upgrade Best Practices

Keep migrations idempotent and ordered by oldVersion, close old connections on versionchange, and test upgrades from every prior version. This keeps returning users' data intact.

Quick Check

Test your understanding of versioning and upgrades.

Recap

You learned versioning and upgrades:

  • Bump the version number to trigger onupgradeneeded.
  • Use oldVersion for incremental, idempotent migrations.
  • The upgrade's versionchange transaction edits schema and data.
  • Migrate records with a cursor and cursor.update.
  • Close old tabs on the versionchange event.

You finished IndexedDB. Next, Service Workers.

Frequently asked questions

Is the “Versioning and Upgrades” lesson free?

Yes — the full text of “Versioning and Upgrades” is free to read here on the web, and the JavaScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the JavaScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Versioning and Upgrades”?

Migrate schemas with version changes. You practise JavaScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start JavaScript Academy?

No prior experience is required. JavaScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Versioning and Upgrades” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this JavaScript Academy lesson?

Yes. Every JavaScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Opening a Database
  2. Transactions and CRUD
  3. Indexes and Queries
  4. Versioning and Upgrades
← Back to JavaScript Academy