diff --git a/web/database/utils/store.js b/web/database/utils/store.js
--- a/web/database/utils/store.js
+++ b/web/database/utils/store.js
@@ -1,6 +1,7 @@
 // @flow
 
 import { reportStoreOpsHandlers } from 'lib/ops/report-store-ops.js';
+import { threadStoreOpsHandlers } from 'lib/ops/thread-store-ops.js';
 import type { ClientStore } from 'lib/types/store-ops-types.js';
 
 import { workerRequestMessageTypes } from '../../types/worker-types.js';
@@ -32,6 +33,16 @@
       reports: reportStoreOpsHandlers.translateClientDBData(data.store.reports),
     };
   }
+  if (data?.store?.threads && data.store.threads.length > 0) {
+    result = {
+      ...result,
+      threadStore: {
+        threadInfos: threadStoreOpsHandlers.translateClientDBData(
+          data.store.threads,
+        ),
+      },
+    };
+  }
   return result;
 }
 
diff --git a/web/database/worker/process-operations.js b/web/database/worker/process-operations.js
--- a/web/database/worker/process-operations.js
+++ b/web/database/worker/process-operations.js
@@ -1,6 +1,7 @@
 // @flow
 
 import type { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js';
+import type { ClientDBThreadStoreOperation } from 'lib/ops/thread-store-ops.js';
 import type {
   ClientDBDraftStoreOperation,
   DraftStoreOperation,
@@ -10,6 +11,10 @@
   ClientDBStoreOperations,
 } from 'lib/types/store-ops-types.js';
 
+import {
+  clientDBThreadInfoToWebThread,
+  webThreadToClientDBThreadInfo,
+} from '../types/entities.js';
 import type { SQLiteQueryExecutor } from '../types/sqlite-query-executor.js';
 
 function processDraftStoreOperations(
@@ -50,11 +55,32 @@
   }
 }
 
+function processThreadStoreOperations(
+  sqliteQueryExecutor: SQLiteQueryExecutor,
+  operations: $ReadOnlyArray<ClientDBThreadStoreOperation>,
+) {
+  for (const operation: ClientDBThreadStoreOperation of operations) {
+    if (operation.type === 'remove_all') {
+      sqliteQueryExecutor.removeAllThreads();
+    } else if (operation.type === 'remove') {
+      const { ids } = operation.payload;
+      sqliteQueryExecutor.removeThreads(ids);
+    } else if (operation.type === 'replace') {
+      sqliteQueryExecutor.replaceThreadWeb(
+        clientDBThreadInfoToWebThread(operation.payload),
+      );
+    } else {
+      throw new Error('Unsupported thread operation');
+    }
+  }
+}
+
 function processDBStoreOperations(
   sqliteQueryExecutor: SQLiteQueryExecutor,
   storeOperations: ClientDBStoreOperations,
 ) {
-  const { draftStoreOperations, reportStoreOperations } = storeOperations;
+  const { draftStoreOperations, reportStoreOperations, threadStoreOperations } =
+    storeOperations;
 
   if (draftStoreOperations) {
     processDraftStoreOperations(sqliteQueryExecutor, draftStoreOperations);
@@ -62,6 +88,9 @@
   if (reportStoreOperations) {
     processReportStoreOperations(sqliteQueryExecutor, reportStoreOperations);
   }
+  if (threadStoreOperations) {
+    processThreadStoreOperations(sqliteQueryExecutor, threadStoreOperations);
+  }
 }
 
 function getClientStore(
@@ -70,7 +99,9 @@
   return {
     drafts: sqliteQueryExecutor.getAllDrafts(),
     messages: [],
-    threads: [],
+    threads: sqliteQueryExecutor
+      .getAllThreadsWeb()
+      .map(t => webThreadToClientDBThreadInfo(t)),
     messageStoreThreads: [],
     reports: sqliteQueryExecutor.getAllReports(),
     users: [],
diff --git a/web/redux/redux-setup.js b/web/redux/redux-setup.js
--- a/web/redux/redux-setup.js
+++ b/web/redux/redux-setup.js
@@ -8,6 +8,7 @@
   deleteAccountActionTypes,
 } from 'lib/actions/user-actions.js';
 import { reportStoreOpsHandlers } from 'lib/ops/report-store-ops.js';
+import { threadStoreOpsHandlers } from 'lib/ops/thread-store-ops.js';
 import baseReducer from 'lib/reducers/master-reducer.js';
 import { mostRecentlyReadThreadSelector } from 'lib/selectors/thread-selectors.js';
 import { isLoggedIn } from 'lib/selectors/user-selectors.js';
@@ -210,9 +211,17 @@
     state = baseReducerResult.state;
 
     const {
-      storeOperations: { draftStoreOperations, reportStoreOperations },
+      storeOperations: {
+        draftStoreOperations,
+        reportStoreOperations,
+        threadStoreOperations,
+      },
     } = baseReducerResult;
-    if (draftStoreOperations.length > 0 || reportStoreOperations.length > 0) {
+    if (
+      draftStoreOperations.length > 0 ||
+      reportStoreOperations.length > 0 ||
+      threadStoreOperations.length > 0
+    ) {
       (async () => {
         const databaseModule = await getDatabaseModule();
         const isSupported = await databaseModule.isDatabaseSupported();
@@ -221,11 +230,14 @@
         }
         const convertedReportStoreOperations =
           reportStoreOpsHandlers.convertOpsToClientDBOps(reportStoreOperations);
+        const convertedThreadStoreOperations =
+          threadStoreOpsHandlers.convertOpsToClientDBOps(threadStoreOperations);
         await databaseModule.schedule({
           type: workerRequestMessageTypes.PROCESS_STORE_OPERATIONS,
           storeOperations: {
             draftStoreOperations,
             reportStoreOperations: convertedReportStoreOperations,
+            threadStoreOperations: convertedThreadStoreOperations,
           },
         });
       })();