diff --git a/src/matrix/storage/idb/Storage.js b/src/matrix/storage/idb/Storage.js
index 9c79b92f..93d55f34 100644
--- a/src/matrix/storage/idb/Storage.js
+++ b/src/matrix/storage/idb/Storage.js
@@ -16,10 +16,14 @@ limitations under the License.
 
 import {Transaction} from "./Transaction.js";
 import { STORE_NAMES, StorageError } from "../common.js";
+import { reqAsPromise } from "./utils.js";
+
+const WEBKITEARLYCLOSETXNBUG_BOGUS_KEY = "782rh281re38-boguskey";
 
 export class Storage {
-    constructor(idbDatabase) {
+    constructor(idbDatabase, hasWebkitEarlyCloseTxnBug) {
         this._db = idbDatabase;
+        this._hasWebkitEarlyCloseTxnBug = hasWebkitEarlyCloseTxnBug;
         const nameMap = STORE_NAMES.reduce((nameMap, name) => {
             nameMap[name] = name;
             return nameMap;
@@ -38,6 +42,11 @@ export class Storage {
         this._validateStoreNames(storeNames);
         try {
             const txn = this._db.transaction(storeNames, "readonly");
+            // https://bugs.webkit.org/show_bug.cgi?id=222746 workaround,
+            // await a bogus idb request on the new txn so it doesn't close early if we await a microtask first
+            if (this._hasWebkitEarlyCloseTxnBug) {
+                await reqAsPromise(txn.objectStore(storeNames[0]).get(WEBKITEARLYCLOSETXNBUG_BOGUS_KEY));
+            }
             return new Transaction(txn, storeNames);
         } catch(err) {
             throw new StorageError("readTxn failed", err);
@@ -48,6 +57,11 @@ export class Storage {
         this._validateStoreNames(storeNames);
         try {
             const txn = this._db.transaction(storeNames, "readwrite");
+            // https://bugs.webkit.org/show_bug.cgi?id=222746 workaround,
+            // await a bogus idb request on the new txn so it doesn't close early if we await a microtask first
+            if (this._hasWebkitEarlyCloseTxnBug) {
+                await reqAsPromise(txn.objectStore(storeNames[0]).get(WEBKITEARLYCLOSETXNBUG_BOGUS_KEY));
+            }
             return new Transaction(txn, storeNames);
         } catch(err) {
             throw new StorageError("readWriteTxn failed", err);
diff --git a/src/matrix/storage/idb/StorageFactory.js b/src/matrix/storage/idb/StorageFactory.js
index b4411469..13860f67 100644
--- a/src/matrix/storage/idb/StorageFactory.js
+++ b/src/matrix/storage/idb/StorageFactory.js
@@ -18,6 +18,7 @@ import {Storage} from "./Storage.js";
 import { openDatabase, reqAsPromise } from "./utils.js";
 import { exportSession, importSession } from "./export.js";
 import { schema } from "./schema.js";
+import { detectWebkitEarlyCloseTxnBug } from "./quirks.js";
 
 const sessionName = sessionId => `hydrogen_session_${sessionId}`;
 const openDatabaseWithSessionId = sessionId => openDatabase(sessionName(sessionId), createStores, schema.length);
@@ -50,8 +51,10 @@ export class StorageFactory {
                 console.warn("no persisted storage, database can be evicted by browser");
             }
         });
+
+        const hasWebkitEarlyCloseTxnBug = await detectWebkitEarlyCloseTxnBug();
         const db = await openDatabaseWithSessionId(sessionId);
-        return new Storage(db);
+        return new Storage(db, hasWebkitEarlyCloseTxnBug);
     }
 
     delete(sessionId) {
diff --git a/src/matrix/storage/idb/quirks.js b/src/matrix/storage/idb/quirks.js
new file mode 100644
index 00000000..b37750f4
--- /dev/null
+++ b/src/matrix/storage/idb/quirks.js
@@ -0,0 +1,41 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+import {openDatabase, txnAsPromise, reqAsPromise} from "./utils.js";
+
+// filed as https://bugs.webkit.org/show_bug.cgi?id=222746
+export async function detectWebkitEarlyCloseTxnBug() {
+    const dbName = "hydrogen_webkit_test_inactive_txn_bug";
+    try {
+        const db = await openDatabase(dbName, db => {
+            db.createObjectStore("test", {keyPath: "key"});
+        }, 1);
+        const readTxn = db.transaction(["test"], "readonly");
+        await reqAsPromise(readTxn.objectStore("test").get("somekey"));
+        // schedule a macro task in between the two txns
+        await new Promise(r => setTimeout(r, 0));
+        const writeTxn = db.transaction(["test"], "readwrite");
+        await Promise.resolve();
+        writeTxn.objectStore("test").add({key: "somekey", value: "foo"});
+        await txnAsPromise(writeTxn);
+    } catch (err) {
+        if (err.name === "TransactionInactiveError") {
+            return true;
+        }
+    }
+    return false;
+}