Block Resolution

When one tab opens the DB at a higher version while another still has it open at an older version, IndexedDB fires a blocked event and the new open request stays pending until all other connections are closed. async-idb-orm handles this automatically so you don’t have to coordinate tabs by hand.

What happens

  1. Tab A has the DB open at version 1.
  2. You deploy version 2; Tab B loads the new code and calls idb(..., { version: 2 }).
  3. The upgrade from 1 → 2 can’t run until every connection from Tab A is closed.
  4. IndexedDB blocks the open in Tab B and fires blocked.

async-idb-orm uses a BroadcastChannel to talk between tabs:

So all tabs end up on the new version without you writing tab-coordination logic.

Optional: reload old tabs

You can force very old tabs to reload (e.g. after breaking changes) via onBeforeReinit:

const VERSION = 1
export const db = idb("users", {
  schema,
  version: VERSION,
  onUpgrade: async (ctx, event) => {
    // handle migrations
  },
  onBeforeReinit: (oldVersion, newVersion) => {
    const breakingChangesVersion = parseInt(localStorage.getItem("breakingChangesVersion") ?? "0")
    if (oldVersion < breakingChangesVersion) {
      window.location.reload()
    }
  },
})

onBeforeReinit runs in the old tab right before it reopens the DB at newVersion. Use it to reload when the old runtime is too far behind (e.g. oldVersion < some stored “minimum” version).

Diagram

Block resolution flow

This coordination runs inside the library; you only need to bump version and implement onUpgrade (and optionally onBeforeReinit) for your migrations.