diff --git a/lib/hooks/login-hooks.js b/lib/hooks/login-hooks.js
--- a/lib/hooks/login-hooks.js
+++ b/lib/hooks/login-hooks.js
@@ -15,6 +15,7 @@
 import { authoritativeKeyserverID } from '../utils/authoritative-keyserver.js';
 import { useDispatchActionPromise } from '../utils/redux-promise-utils.js';
 import { useSelector, useDispatch } from '../utils/redux-utils.js';
+import { waitUntilDatabaseDeleted } from '../utils/wait-until-db-deleted.js';
 
 // We can't just do everything in one async callback, since the server calls
 // would get bound to Redux state from before the login. In order to pick up the
@@ -135,6 +136,7 @@
         resolve();
       } catch (e) {
         void dispatchActionPromise(logOutActionTypes, identityLogOut());
+        await waitUntilDatabaseDeleted();
         reject(e);
       } finally {
         setCurrentStep(inactiveStep);
diff --git a/lib/utils/wait-until-db-deleted.js b/lib/utils/wait-until-db-deleted.js
new file mode 100644
--- /dev/null
+++ b/lib/utils/wait-until-db-deleted.js
@@ -0,0 +1,20 @@
+// @flow
+
+let waitingOnDatabaseDeletion = [];
+
+function waitUntilDatabaseDeleted(): Promise<void> {
+  return new Promise(resolve => {
+    waitingOnDatabaseDeletion.push(resolve);
+  });
+}
+
+function reportDatabaseDeleted() {
+  const callbacksToTrigger = waitingOnDatabaseDeletion;
+  waitingOnDatabaseDeletion = [];
+
+  for (const callback of callbacksToTrigger) {
+    callback();
+  }
+}
+
+export { waitUntilDatabaseDeleted, reportDatabaseDeleted };
diff --git a/native/account/registration/registration-server-call.js b/native/account/registration/registration-server-call.js
--- a/native/account/registration/registration-server-call.js
+++ b/native/account/registration/registration-server-call.js
@@ -24,6 +24,7 @@
 import { useDispatch } from 'lib/utils/redux-utils.js';
 import { usingCommServicesAccessToken } from 'lib/utils/services-utils.js';
 import { setURLPrefix } from 'lib/utils/url-utils.js';
+import { waitUntilDatabaseDeleted } from 'lib/utils/wait-until-db-deleted.js';
 
 import type {
   RegistrationServerCallInput,
@@ -373,6 +374,7 @@
           deleteAccountActionTypes,
           discardIdentityAccountPromise,
         );
+        await waitUntilDatabaseDeleted();
         reject(keyserverAuthException);
         setCurrentStep(inactiveStep);
       } finally {
diff --git a/native/data/sqlite-data-handler.js b/native/data/sqlite-data-handler.js
--- a/native/data/sqlite-data-handler.js
+++ b/native/data/sqlite-data-handler.js
@@ -28,6 +28,7 @@
 import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js';
 import { useDispatch } from 'lib/utils/redux-utils.js';
 import { supportingMultipleKeyservers } from 'lib/utils/services-utils.js';
+import { reportDatabaseDeleted } from 'lib/utils/wait-until-db-deleted.js';
 
 import { resolveKeyserverSessionInvalidationUsingNativeCredentials } from '../account/legacy-recover-keyserver-session.js';
 import { authoritativeKeyserverID } from '../authoritative-keyserver.js';
@@ -42,6 +43,7 @@
 async function clearSensitiveData() {
   try {
     await commCoreModule.clearSensitiveData();
+    reportDatabaseDeleted();
   } catch (error) {
     console.log(
       `Error clearing SQLite database: ${
diff --git a/web/shared-worker/sqlite-data-handler.js b/web/shared-worker/sqlite-data-handler.js
--- a/web/shared-worker/sqlite-data-handler.js
+++ b/web/shared-worker/sqlite-data-handler.js
@@ -5,6 +5,7 @@
 import { shouldClearData } from 'lib/shared/data-utils.js';
 import { getMessageForException } from 'lib/utils/errors.js';
 import { useDispatch } from 'lib/utils/redux-utils.js';
+import { reportDatabaseDeleted } from 'lib/utils/wait-until-db-deleted.js';
 
 import { getCommSharedWorker } from './shared-worker-provider.js';
 import { useSelector } from '../redux/redux-utils.js';
@@ -43,6 +44,7 @@
     ) {
       try {
         await sharedWorker.init({ clearDatabase: true });
+        reportDatabaseDeleted();
       } catch (error) {
         console.error(
           `Error clearing sensitive data: ${